是否有.NET泛型BitArray? 我只找到了非一般的一个。
能有一个通用的BitArray? (即会是合理的?)
编辑:
也许我应该说类型安全不是通用的。
基本上当你枚举类型object
,岂不是int
或bool
? 或者他们中的一个在另一个成员枚举提供?
例:
foreach (bool bit in myBitArray)
{
}
编辑:
我刚刚检查了的枚举BitArray
类,但一切都返回一个object
,除了.Current
属性:
public virtual object Current
不,没有。
我甚至不知道是否有一个什么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;
}
我从一个快速的基准(好奇心战胜了我)发现了是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
。 你可以节省时间和使用反射来复制大多数的研究BitArray
的代码,因为类是密封的(不能继承并添加功能),以防万一有位变换优化学习的榜样。
编辑:施特鲁克的建议,复制代码反射出来的。 有些东西,如迭代器和关闭,产生怪异生成的代码,你不想直接反正复制。
BitArray是从NET 1.x的时代就是一个专门收集类。 只要你使用它是很类型安全ba.Set(int, bool)
和索引属性。
什么是“不是类型安全”是枚举,BitArray实现IEnumerable但不是IEnumerable的<布尔>。 所以琼是正确的,使用foreach()
涉及从对象铸造布尔。
但是,这是一个真正的问题? 当与它们的位置结合在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<bool>
:
public static IEnumerable<bool> 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<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];
}
}
结果(姓名,迭代,总时长,评分(最高分是坏的)数):
============ 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
什么是你会传递给泛型类型参数的例子BitArray<T>
如果它存在?
BitArray
定义为:
管理位值,其被表示为布尔值的紧凑阵列,其中真表示该位是(1)和假指示位为关闭(0)。
这种类型是位的最佳的排列,没有别的。 还有就是要使其成为通用的,因为没有价值没有成员可能被分解出来的类型。 像这样的任何专门收集可以,虽然作为一个封闭构造类型的某些父泛型集合的。 换句话说, BitArray
是一种像List<Boolean>
(加入当然许多有用的方法)。
编辑:是的,这个类型实现IEnumerable
和未实现IEnumerable<T>
-这很可能是由于这样的事实,这是一个较旧类型,并没有更新。 请记住,你可以使用Enumerable.Cast<TResult>
解决此问题非常:
yourBitArray.Cast<bool>();
你将有一个通用的版本有什么可能的原因? 可能一个BitArray可能位,或者是变成位的情况是布尔旁边使用什么类型的?
更新:它是类型安全的。 如果你正在做一个foreach(在bitArray VAR位),那么位将显示为一个对象,但你可以很容易做的foreach(在bitArray布尔位),这种情况对于实现IEnumerable,而不是所有集合IEnumerable<T>.