Is there a generic (type-safe) BitArray in .NET?

Is there a common BitArray in .NET? I did not find a generic option.

Could there be a generic BitArray? (i.e. would it be reasonable?)


Edit:

Perhaps I should have said that type-safe is not common.

Basically, when you list a type as object , should it not be int or bool ? Or is one of them provided in another counter?


Example:

 foreach (bool bit in myBitArray) { } 

Edit:

I just checked the enumerator of the BitArray class, but everything returns an object except .Current :

 public virtual object Current 
+4
source share
5 answers

No no.

I'm not even sure which part of BitArray would be common if it were.

It's easy to create an extension method to take BitArray and return << β†’ bool[] or List<bool> using a for loop on BitArray . The for loop will not include boxing, since you will use the BitArray indexer, and the bool[] List<bool> can be enumerated without a box.

Example extension method:

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

What I found from a quick test (curiosity overcame me) was that foreach (bool b in myBitArray.ToList()) took 75% -85% of the time when foreach (bool b in myBitArray) . This creates a list every time. Creating a list once and repeating it many times took from 20% to 25% of the time spent on foreach (bool b in myBitArray) . You could use this only if you need to iterate over the bool values ​​repeatedly and know that they will not be changed from the moment myBitArray.ToList() called.

foreach (bool b in Enumerable.Cast<bool(myBitArray)) took 150% of the time when foreach (bool b in myBitArray) took.

Another edit: I would say that since this is a game, it probably makes sense for you to do your best to have a very meager iteration without boxing / unpacking, even if it means writing your own BitArray . You could save time and use Reflector to copy most of the training BitArray code, since the class is sealed (cannot inherit and add functionality), just in case you can optimize bit-twiddling.

Edit: Removed offer to copy code from Reflector. Some things, such as iterators and closures, produce weird generated code that you don't want to copy directly anyway.

+8
source

BitArray is a specialized collection class from the NET 1.x era. This is safe if you use ba.Set(int, bool) and the indexer property.

What is 'not typesafe' is an enumeration, BitArray implements IEnumerable, but not IEnumerable <BOOL>. So, Joan is right, using foreach() involves casting from object to bool.

But is this a real problem? Elements in BitArray are logical and make sense only in combination with their position. Note that BitArray does not have an Add() method, just Set(i, true) .

So, the simple answer is: do not use foreach() or anything else based on IEnumerable. It only creates a stream of true / false values ​​that are unlikely to be useful.

In the following snippet, BitArray is absolutely safe and effective:

 BitArray isEven = ...; for(int i = 0; i < isEven.Count; i++) { isEven.Set(i, i % 2 == 0); } 
+9
source

You can BitArray over BitArray without a box or convert it to List<bool> :

 public static IEnumerable<bool> GetTypeSafeEnumerator(this BitArray ba) { for (int i = 0; i < ba.Length; i++) yield return ba[i]; } 

This should be faster than converting to a list, and it certainly takes up much less memory.

Of course, it will still be slower than the usual old for loop, and if you really need performance, you should use

 for (int i = 0; i < ba.Length; i++) { bool b = ba[i]; ... } 

Test using 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]; } } 

Results (name, number of iterations, total duration, evaluation (high score is bad)):

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

What is an example of a typical type argument that you would switch to BitArray<T> if it existed?

BitArray defined as:

Controls a compact array of bit values ​​that are represented as Boolean, where true indicates that the bit is on (1) and false indicates that the bit is off (0).

This type is an optimized array of bits, and nothing more. There is no value in making it general, since there are no participants that can be accounted for from the type. Any specialized collection, like this one, can be, although closed, constructed as a kind of some parental general collection. In other words, BitArray is similar to List<Boolean> (of course, many useful methods have been added).

Edit: Yes, this type implements IEnumerable and does not implement IEnumerable<T> - this is most likely due to the fact that it is older and not updated. Remember that you can use Enumerable.Cast<TResult> to get around this problem:

 yourBitArray.Cast<bool>(); 
+2
source

What is the possible reason for the general version? What type of BitArray can be used next to bits or boolean elements that turn into bits as an argument?

Updated: This is a safe type. If you do foreach (var bit in bitArray) then the bit will be displayed as an object, but you can just as easily make foreach (bool bit in bitArray), this happens for all collections that implement IEnumerable, not IEnumerable<T>.

+2
source

All Articles