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

Joa*_*nge 4 .net c# bitarray

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

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


编辑:

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

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


例:

foreach (bool bit in myBitArray)
{

}
Run Code Online (Sandbox Code Playgroud)

编辑:

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

public virtual object Current
Run Code Online (Sandbox Code Playgroud)

Hen*_*man 9

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)


Joe*_*ant 8

不,没有.

如果有的话,我甚至不确定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复制代码的建议.有些东西,如迭代器和闭包,会产生奇怪的生成代码,无论如何都不想直接复制.


Ale*_*nov 7

你可以在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)