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

时间:2009-07-31 18:04:24

标签: c# .net bitarray

.NET中是否有通用的BitArray?我只发现了非通用的那个。

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


编辑:

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

基本上,当您将类型枚举为object时,它应该不是int还是bool?或者其中一个在另一个成员普查员中提供?


实施例

foreach (bool bit in myBitArray)
{

}

编辑:

我刚检查了BitArray类的枚举器,但除了object属性外,所有内容都返回.Current

public virtual object Current

5 个答案:

答案 0 :(得分:9)

BitArray是NET 1.x时代的专业集合类。只要您使用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);
}

答案 1 :(得分:8)

不,没有。

我甚至不确定BitArray中哪一部分是通用的。

使用BitArray创建一个扩展方法来获取bool[]并返回 List<bool> for并不难循环BitArrayfor循环不会涉及拳击,因为您将使用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())花费了foreach (bool b in myBitArray)的75%到85%的时间。这每次创建列表。创建列表一次并迭代多次占用foreach (bool b in myBitArray)所花费的时间的20%到25%。如果您需要多次迭代bool值并且知道它们在您调用myBitArray.ToList()时不会发生更改,则只能利用它。< / p>

foreach (bool b in Enumerable.Cast<bool(myBitArray))花费了foreach (bool b in myBitArray)花费的时间的150%。

另一个编辑:我会说,因为它是一款游戏,所以你可以做任何事情来做一个非常精益的迭代,没有装箱/拆箱,甚至如果这意味着自己编写BitArray。您可以节省时间并使用Reflector复制大部分学习BitArray的代码,因为该类是密封的(无法继承和添加功能),以防万一是一个有点擅长的优化来学习。

编辑:了解将代码复制出Reflector的建议。有些东西,如迭代器和闭包,会产生奇怪的生成代码,无论如何都不想直接复制。

答案 2 :(得分:7)

您可以在不装箱的情况下迭代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];
    }
}

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

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

答案 3 :(得分:2)

如果它存在,您将传递给BitArray<T>的泛型类型参数的示例是什么?

BitArray定义为:

  

管理一个紧凑的位值数组,   代表布尔人,   其中true表示该位是   on(1)和false表示该位   关(0)。

这种类型是一个优化的位数组,没有别的。将它设为通用没有任何价值,因为no members可以从类型中分解出来。像这样的任何专门的集合可以作为一些父通用集合的封闭构造类型。换句话说,BitArray有点像List<Boolean>(当然会添加许多有用的方法)。

修改:是的,此类型实现IEnumerable并且未实现IEnumerable<T> - 这很可能是因为它是旧类型并且未更新。请记住,您可以使用Enumerable.Cast<TResult>解决此问题:

yourBitArray.Cast<bool>();

答案 4 :(得分:2)

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

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