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