是否有.NET泛型(类型安全)BitArray?(Is there a generic (type-

2019-09-21 18:04发布

是否有.NET泛型BitArray? 我只找到了非一般的一个。

能有一个通用的BitArray? (即会是合理的?)


编辑:

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

基本上当你枚举类型object ,岂不是intbool ? 或者他们中的一个在另一个成员枚举提供?


例:

foreach (bool bit in myBitArray)
{

}

编辑:

我刚刚检查了的枚举BitArray类,但一切都返回一个object ,除了.Current属性:

public virtual object Current

Answer 1:

不,没有。

我甚至不知道是否有一个什么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的代码,因为类是密封的(不能继承并添加功能),以防万一有位变换优化学习的榜样。

编辑:施特鲁克的建议,复制代码反射出来的。 有些东西,如迭代器和关闭,产生怪异生成的代码,你不想直接反正复制。



Answer 2:

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);
}


Answer 3:

可以遍历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


Answer 4:

什么是你会传递给泛型类型参数的例子BitArray<T>如果它存在?

BitArray定义为:

管理位值,其被表示为布尔值的紧凑阵列,其中真表示该位是(1)和假指示位为关闭(0)。

这种类型是位的最佳的排列,没有别的。 还有就是要使其成为通用的,因为没有价值没有成员可能被分解出来的类型。 像这样的任何专门收集可以,虽然作为一个封闭构造类型的某些父泛型集合的。 换句话说, BitArray是一种像List<Boolean> (加入当然许多有用的方法)。

编辑:是的,这个类型实现IEnumerable和未实现IEnumerable<T> -这很可能是由于这样的事实,这是一个较旧类型,并没有更新。 请记住,你可以使用Enumerable.Cast<TResult>解决此问题非常:

yourBitArray.Cast<bool>();


Answer 5:

你将有一个通用的版本有什么可能的原因? 可能一个BitArray可能位,或者是变成位的情况是布尔旁边使用什么类型的?

更新:它是类型安全的。 如果你正在做一个foreach(在bitArray VAR位),那么位将显示为一个对象,但你可以很容易做的foreach(在bitArray布尔位),这种情况对于实现IEnumerable,而不是所有集合IEnumerable<T>.



文章来源: Is there a generic (type-safe) BitArray in .NET?
标签: c# .net bitarray