.NET中是否存在通用(类型安全)BitArray?

.NET中是否有通用的BitArray? 我只找到了非通用的。

可以有一个通用的BitArray吗? (即它会合理吗?)


编辑:

也许我应该说类型安全不通用。

基本上当你将类型枚举为object ,它应该不是intbool吗? 或者其中一个在另一个成员调查员中提供?


例:

 foreach (bool bit in myBitArray) { } 

编辑:

我刚刚检查了BitArray类的枚举器,但是除了.Current属性之外,所有东西都返回一个object

 public virtual object Current 

不,没有。

如果有的话,我甚至不确定BitArray的哪一部分是通用的。

创建一个扩展方法来获取BitArray并使用BitArray上的for循环返回bool[] List并不难。 for循环不会涉及拳击,因为你将使用BitArray的索引器,并且bool[] List也可以在没有装箱的情况下枚举。

示例扩展方法:

 static List ToList( this BitArray ba ) { List l = new List(ba.Count); for ( int i = 0 ; i < ba.Count ; i++ ) { l.Add( ba[ i ] ); } return l; } 

我从快速基准(好奇心克服了我)中发现的是, foreach (bool b in myBitArray.ToList())foreach (bool b in myBitArray.ToList()) 75%到85%的时间foreach (bool b in myBitArray) 。 这每次都会创建列表。 创建一次列表并多次迭代它需要20%到25%的foreach (bool b in myBitArray)花费的时间。 如果你需要多次遍历bool值并且知道它们在你调用myBitArray.ToList()时没有改变,你myBitArray.ToList()

foreach (bool b in Enumerable.Cast中的foreach (bool b in myBitArray)占用了foreach (bool b in myBitArray) foreach (bool b in Enumerable.Cast占用的150%的时间。

还有另一个编辑:我会说,因为它是一款游戏,所以你可以做任何事情来做一个没有装箱/拆箱的非常精益的迭代,即使这意味着你自己编写了BitArray 。 您可以节省时间并使用Reflector来复制大部分研究BitArray的代码,因为类是密封的(不能inheritance和添加function),以防万一有点奇怪的优化需要学习。

编辑:打破从reflection器复制代码的建议。 有些东西,比如迭代器和闭包,会产生奇怪的生成代码,你不想直接复制它们。

BitArray是NET 1.x时代的专业集合类。 只要你使用ba.Set(int, bool)和indexer属性ba.Set(int, bool)它就是类型安全的。

什么是’not typesafe’是枚举,BitArray实现IEnumerable而不是IEnumerable 。 所以Joan是对的,使用foreach()涉及从对象转换为bool。

但这是一个真正的问题吗? BitArray中的元素是布尔值,只有与它们的位置结合才有意义。 请注意,BitArray没有Add()方法,只有Set(i, true)

所以简单的答案是:不要使用foreach() ,或基于IEnumerable的任何其他东西。 它只产生一个很难用的真/假值流。

在下面的代码片段中,BitArray是完全类型安全且高效的:

 BitArray isEven = ...; for(int i = 0; i < isEven.Count; i++) { isEven.Set(i, i % 2 == 0); } 

您可以在没有装箱的情况下迭代BitArray 将其转换为List

 public static IEnumerable GetTypeSafeEnumerator(this BitArray ba) { for (int i = 0; i < ba.Length; i++) yield return ba[i]; } 

这应该比转换到列表更快,并且肯定会减少更少的内存。

当然,它仍然比普通的for循环慢,如果你真的需要性能,你应该使用

 for (int i = 0; i < ba.Length; i++) { bool b = ba[i]; ... } 

使用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( "Different looping methods") .Plus(PlainFor, "Plain for loop") .Plus(ForEachBool, "foreach(bool bit in bitArray)") .Plus(CastBool, "foreach(bool bit in bitArray.Cast)") .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( "Avoiding repeated conversions") .Plus(PlainFor1, "Plain for loop") .Plus(CastBool1, "foreach(bool bit in bitArray.Cast)") .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(); 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()) { 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 ToList(this BitArray ba) { List l = new List(ba.Count); for (int i = 0; i < ba.Count; i++) { l.Add(ba[i]); } return l; } public static IEnumerable GetTypeSafeEnumerator(this BitArray ba) { for (int i = 0; i < ba.Length; i++) yield return ba[i]; } } 

结果(姓名,迭代次数,总持续时间,得分(高分为差)):

 ============ 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) 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) 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 

如果它存在,你将传递给BitArray的generics类型参数的例子是什么?

BitArray定义为:

管理一个紧凑的位值数组,表示为布尔值,其中true表示该位为on(1),false表示该位为off(0)。

这种类型是一个优化的位数组,没有别的。 将它作为通用没有任何价值,因为没有可以在该类型之外进行分解的成员 。 像这样的任何专门的集合可以作为一些父通用集合的封闭构造类型。 换句话说, BitArray有点像List (当然还添加了许多有用的方法)。

编辑:是的,这种类型实现了IEnumerable并且没有实现IEnumerable – 这很可能是因为它是一个较旧的类型并且没有更新。 请记住,您可以使用Enumerable.Cast来解决这个问题:

 yourBitArray.Cast(); 

您对通用版本有什么可能的原因? BitArray可能在比特旁边使用什么类型,或者根据情况转换为比特的布尔值?

更新:它是类型安全的。 如果你正在做一个foreach(bitArray中的var位),那么bit将作为一个对象出现,但是你可以很容易地做foreach(bitArray中的bool位),这对于实现IEnumerable而不是IEnumerable.所有集合都会发生IEnumerable.