C# 在.NET中是否存在通用(类型安全)位数组?

C# 在.NET中是否存在通用(类型安全)位数组?,c#,.net,bitarray,C#,.net,Bitarray,.NET中是否有通用位数组?我只找到了非通用的 是否存在通用位数组?(即是否合理?) 编辑: 也许我应该说类型安全不是泛型的 基本上,当您将类型枚举为object时,它应该不是int还是bool?或者在另一个成员枚举器中提供其中一个 例子: 编辑: 我刚刚检查了位数组类的枚举数,但是除了之外,所有内容都返回一个对象。当前的属性: public virtual object Current 不,没有 我甚至不确定如果有一个位数组,它的哪个部分是通用的 创建一个扩展方法来获取BitArray

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

是否存在通用位数组?(即是否合理?)


编辑: 也许我应该说类型安全不是泛型的

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


例子:
编辑: 我刚刚检查了
位数组
类的枚举数,但是除了
之外,所有内容都返回一个
对象
。当前的
属性:

public virtual object Current
不,没有

我甚至不确定如果有一个位数组,它的哪个部分是通用的

创建一个扩展方法来获取
BitArray
并使用
BitArray
上的
for
循环返回
bool[]
List
,并不难。
for
循环不涉及装箱,因为您将使用
位数组
的索引器,并且
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;
}
静态列表列表(此位数组ba){
列表l=新列表(ba.计数);
for(int i=0;i
我从一个快速基准测试中发现(好奇心战胜了我)foreach(myBitArray.ToList()中的bool b)花费了
foreach(myBitArray中的bool b)
75%到85%的时间。每次都会创建一个列表。创建一次列表并对其进行多次迭代所花费的时间是
foreach(myBitArray中的bool b)
所花费时间的20%到25%。如果需要多次迭代
bool
值,并且知道它们在调用
myBitArray.ToList()时不会发生更改,则只能利用这一点


foreach(Enumerable.Cast中的bool b如果存在,将传递给
BitArray
的泛型类型参数的示例是什么

定义如下:

管理位值的紧凑数组, 以布尔形式表示, 其中,true表示位为 on(1)和false表示位为 关闭(0)

此类型是一个优化的位数组,除此之外没有其他内容。使其成为泛型没有任何价值,因为存在可以从该类型中分解出来的内容。任何像此类型的专用集合都可以看作是某个父泛型集合的封闭构造类型。换句话说,
bitary
有点像
List
(当然添加了许多有用的方法)

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

yourBitArray.Cast<bool>();
yourBitArray.Cast();

对于通用版本,您有什么可能的理由?除了位或布尔值(根据情况转换为位)之外,位数组可能使用什么类型

更新:
它是类型安全的。如果您正在执行foreach(位数组中的var位),则位将显示为对象,但您也可以轻松地执行foreach(位数组中的bool位),所有实现IEnumerable而不是
IEnumerable的集合都会发生这种情况。

BitArray是Net1.x时代的一个专门集合类。只要使用
ba.Set(int,bool)
和indexer属性,它是非常安全的类型

“非类型安全”的是枚举,BitArray实现IEnumerable但不是IEnumerable。因此Joan是对的,使用
foreach()
涉及从对象到bool的强制转换

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

因此,简单的答案是:不要使用
foreach()
,或者任何基于IEnumerable的东西。它只会生成一个几乎没有用处的真/假值流

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

BitArray isEven = ...;
for(int i = 0; i < isEven.Count; i++) 
{
   isEven.Set(i, i % 2 == 0);
}
位数组isEven=。。。;
for(int i=0;i
您可以迭代
位数组
,而无需装箱或将其转换为
列表

基准使用:

公共静态类Class1{
私有常量int N=10000;
私有常数int M=100;
公共静态void Main(){
var bitArray=新的位数组(N);
var results1=新的测试套件(
“不同的循环方法”)
.Plus(普通for,“普通for循环”)
.Plus(ForEachBool,“foreach(位数组中的bool位)”)
.Plus(CastBool,“foreach(bitArray.Cast中的bool位)”)
.Plus(TypeSafeEnumerator,“foreach(bitArray.GetTypeSafeEnumerator()中的布尔位”)
.Plus(UseToList,“foreach(bitArray.ToList()中的bool位)”
.RunTests(位数组,0);
results1.Display(ResultColumns.All,results1.FindBest());
var results2=新的测试套件(
“避免重复转换”)
.Plus(PlainFor1,“plainforloop”)
.Plus(CastBool1,“foreach(bitArray.Cast中的bool位)”)
.Plus(TypeSafeEnumerator 1,“foreach(bitArray.GetTypeSafeEnumerator()中的布尔位”)
.Plus(UseToList1,“foreach(bitArray.ToList()中的布尔位)”
.RunTests(位数组,0);
results2.Display(ResultColumns.All,results2.FindBest());
}
专用静态整数PlainFor1(位数组arg){
int j=0;
对于(int k=0;kBitArray isEven = ...;
for(int i = 0; i < isEven.Count; i++) 
{
   isEven.Set(i, i % 2 == 0);
}
public static IEnumerable<bool> GetTypeSafeEnumerator(this BitArray ba) {
    for (int i = 0; i < ba.Length; i++)
        yield return ba[i];
}
for (int i = 0; i < ba.Length; i++) {
    bool b = ba[i];
    ...
}
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