.NET中是否有通用的BitArray?我只找到了非通用的.
可以有一个通用的BitArray吗?(即它是否合理?)
也许我应该说类型安全不通用.
基本上当你枚举类型时object,它应该不是int或bool?或者其中一个在另一个成员调查员中提供?
foreach (bool bit in myBitArray)
{
}
Run Code Online (Sandbox Code Playgroud)
我刚刚检查了BitArray类的枚举器,但是所有东西都返回了一个objectexcept .Current属性:
public virtual object Current
Run Code Online (Sandbox Code Playgroud)
BitArray是NET 1.x时代的专业集合类.只要您使用ba.Set(int, bool)和索引器属性,它是非常类型安全的.
什么是'not typesafe'是枚举,BitArray实现IEnumerable而不是IEnumerable <bool>.所以琼是对的,使用foreach()涉及从对象铸造到布尔.
但这是一个真正的问题吗?BitArray中的元素是布尔值,只有与它们的位置结合才有意义.请注意,BitArray没有Add()方法,只有a Set(i, true).
所以简单的答案是:不要使用foreach(),或基于IEnumerable的任何其他东西.它只产生一个很难用的真/假值流.
在下面的代码片段中,BitArray是完全类型安全且高效的:
BitArray isEven = ...;
for(int i = 0; i < isEven.Count; i++)
{
isEven.Set(i, i % 2 == 0);
}
Run Code Online (Sandbox Code Playgroud)
不,没有.
如果有的话,我甚至不确定BitArray的哪一部分是通用的.
创建一个扩展方法来获取BitArray和返回一个bool[]或List<bool>使用一个for循环并不难BitArray.该for循环将不涉及拳击,因为你会使用BitArray的索引,而可以在不拳击被列举为好.bool[]List<bool>
示例扩展方法:
static List<bool> ToList( this BitArray ba ) {
List<bool> l = new List<bool>(ba.Count);
for ( int i = 0 ; i < ba.Count ; i++ ) {
l.Add( ba[ i ] );
}
return l;
}
Run Code Online (Sandbox Code Playgroud)
我从快速基准(好奇心克服了我)中发现的foreach (bool b in myBitArray.ToList())是75%到85%的时间foreach (bool b in myBitArray).这每次创建列表.创建一次列表并多次迭代它需要花费20%到25%的时间foreach (bool b in myBitArray).如果您需要bool多次迭代这些值并且知道它们从您调用时起不会发生更改,您只能利用它myBitArray.ToList().
foreach (bool b in Enumerable.Cast<bool(myBitArray))占用了150%的时间foreach (bool b in myBitArray).
还有另一个编辑:我会说,因为它是一款游戏,所以你可以做任何事情来做一个非常精益的迭代而没有装箱/拆箱,即使这意味着自己编写BitArray.你可以节省时间并使用Reflector来复制大部分学习BitArray代码,因为课程是密封的(不能继承和添加功能),以防万一有点啰嗦的优化需要学习.
编辑:打破从Reflector复制代码的建议.有些东西,如迭代器和闭包,会产生奇怪的生成代码,无论如何都不想直接复制.
你可以在BitArray没有装箱的情况下迭代或将其转换为List<bool>:
public static IEnumerable<bool> GetTypeSafeEnumerator(this BitArray ba) {
for (int i = 0; i < ba.Length; i++)
yield return ba[i];
}
Run Code Online (Sandbox Code Playgroud)
这应该比转换到列表更快,并且肯定会减少更少的内存.
当然,它仍然比普通的旧for循环慢,如果你真的需要性能,你应该使用
for (int i = 0; i < ba.Length; i++) {
bool b = ba[i];
...
}
Run Code Online (Sandbox Code Playgroud)
使用MiniBench进行基准测试:
public static class Class1 {
private const int N = 10000;
private const int M = 100;
public static void Main() {
var bitArray = new BitArray(N);
var results1 = new TestSuite<BitArray, int>(
"Different looping methods")
.Plus(PlainFor, "Plain for loop")
.Plus(ForEachBool, "foreach(bool bit in bitArray)")
.Plus(CastBool, "foreach(bool bit in bitArray.Cast<bool>)")
.Plus(TypeSafeEnumerator, "foreach(bool bit in bitArray.GetTypeSafeEnumerator())")
.Plus(UseToList, "foreach(bool bit in bitArray.ToList())")
.RunTests(bitArray, 0);
results1.Display(ResultColumns.All, results1.FindBest());
var results2 = new TestSuite<BitArray, int>(
"Avoiding repeated conversions")
.Plus(PlainFor1, "Plain for loop")
.Plus(CastBool1, "foreach(bool bit in bitArray.Cast<bool>)")
.Plus(TypeSafeEnumerator1, "foreach(bool bit in bitArray.GetTypeSafeEnumerator())")
.Plus(UseToList1, "foreach(bool bit in bitArray.ToList())")
.RunTests(bitArray, 0);
results2.Display(ResultColumns.All, results2.FindBest());
}
private static int PlainFor1(BitArray arg) {
int j = 0;
for (int k = 0; k < M; k++) {
for (int i = 0; i < arg.Length; i++) {
j += arg[i] ? 1 : 0;
}
}
return j;
}
private static int CastBool1(BitArray arg) {
int j = 0;
var ba = arg.Cast<bool>();
for (int k = 0; k < M; k++) {
foreach (bool b in ba) {
j += b ? 1 : 0;
}
}
return j;
}
private static int TypeSafeEnumerator1(BitArray arg) {
int j = 0;
var ba = arg.GetTypeSafeEnumerator();
for (int k = 0; k < M; k++) {
foreach (bool b in ba) {
j += b ? 1 : 0;
}
}
return j;
}
private static int UseToList1(BitArray arg) {
int j = 0;
var ba = arg.ToList();
for (int k = 0; k < M; k++) {
foreach (bool b in ba) {
j += b ? 1 : 0;
}
}
return j;
}
private static int PlainFor(BitArray arg) {
int j = 0;
for (int i = 0; i < arg.Length; i++) {
j += arg[i] ? 1 : 0;
}
return j;
}
private static int ForEachBool(BitArray arg) {
int j = 0;
foreach (bool b in arg) {
j += b ? 1 : 0;
}
return j;
}
private static int CastBool(BitArray arg) {
int j = 0;
foreach (bool b in arg.Cast<bool>()) {
j += b ? 1 : 0;
}
return j;
}
private static int TypeSafeEnumerator(BitArray arg) {
int j = 0;
foreach (bool b in arg.GetTypeSafeEnumerator()) {
j += b ? 1 : 0;
}
return j;
}
private static int UseToList(BitArray arg) {
int j = 0;
foreach (bool b in arg.ToList()) {
j += b ? 1 : 0;
}
return j;
}
public static List<bool> ToList(this BitArray ba) {
List<bool> l = new List<bool>(ba.Count);
for (int i = 0; i < ba.Count; i++) {
l.Add(ba[i]);
}
return l;
}
public static IEnumerable<bool> GetTypeSafeEnumerator(this BitArray ba) {
for (int i = 0; i < ba.Length; i++)
yield return ba[i];
}
}
Run Code Online (Sandbox Code Playgroud)
结果(名称,迭代次数,总持续时间,得分(高分为差)):
============ Different looping methods ============
Plain for loop 456899 0:28.087 1,00
foreach(bool bit in bitArray) 135799 0:29.188 3,50
foreach(bool bit in bitArray.Cast<bool>) 81948 0:33.183 6,59
foreach(bool bit in bitArray.GetTypeSafeEnumerator()) 179956 0:27.508 2,49
foreach(bool bit in bitArray.ToList()) 161883 0:27.793 2,79
============ Avoiding repeated conversions ============
Plain for loop 5381 0:33.247 1,00
foreach(bool bit in bitArray.Cast<bool>) 745 0:28.273 6,14
foreach(bool bit in bitArray.GetTypeSafeEnumerator()) 2304 0:27.457 1,93
foreach(bool bit in bitArray.ToList()) 4603 0:30.583 1,08
Run Code Online (Sandbox Code Playgroud)