Ответ 1
BitArray
сможет обрабатывать произвольное количество логических значений, тогда как a byte
будет содержать только 8, int
всего 32 и т.д. Это будет самая большая разница между ними.
Кроме того, BitArray
реализует IEnumerable
, где интегрального типа, очевидно, нет. Так что все зависит от требований вашего проекта; если вам нужен IEnumerable
или подобный массиву интерфейс, перейдите к BitArray
.
Я бы использовал bool[]
для любого решения, просто потому, что он более явный в том, какие данные вы отслеживаете. Т
BitArray
или bitfield
будет использовать приблизительно 1/8-е пространство a bool[]
, потому что они "упаковывают" 8 булевых значений в один байт, тогда как a bool
сам возьмет на себя весь 8- бит. Космическое преимущество использования битового поля или BitArray
не имеет значения, пока вы не сохраните лоты bools
. (Математика остается до читателя:-))
Benchmark
Результаты. Для моей примитивной тестовой среды кажется, что BitArray
немного быстрее, но находится на том же уровне, что и сам с интегральным типом. Также был протестирован bool[]
, что было неудивительно самым быстрым. Доступ к одному байту в памяти будет менее сложным, чем доступ к отдельным битам в разных байтах.
Testing with 10000000 operations:
A UInt32 bitfield took 808 ms.
A BitArray (32) took 574 ms.
A List<bool>(32) took 436 ms.
код:
class Program
{
static void Main(string[] args)
{
Random r = new Random();
r.Next(1000);
const int N = 10000000;
Console.WriteLine("Testing with {0} operations:", N);
Console.WriteLine(" A UInt32 bitfield took {0} ms.", TestBitField(r, N));
Console.WriteLine(" A BitArray (32) took {0} ms.", TestBitArray(r, N));
Console.WriteLine(" A List<bool>(32) took {0} ms.", TestBoolArray(r, N));
Console.Read();
}
static long TestBitField(Random r, int n)
{
UInt32 bitfield = 0;
var sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++) {
SetBit(ref bitfield, r.Next(32), true);
bool b = GetBit(bitfield, r.Next(32));
SetBit(ref bitfield, r.Next(32), b);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
static bool GetBit(UInt32 x, int bitnum) {
if (bitnum < 0 || bitnum > 31)
throw new ArgumentOutOfRangeException("Invalid bit number");
return (x & (1 << bitnum)) != 0;
}
static void SetBit(ref UInt32 x, int bitnum, bool val)
{
if (bitnum < 0 || bitnum > 31)
throw new ArgumentOutOfRangeException("Invalid bit number");
if (val)
x |= (UInt32)(1 << bitnum);
else
x &= ~(UInt32)(1 << bitnum);
}
static long TestBitArray(Random r, int n)
{
BitArray b = new BitArray(32, false); // 40 bytes
var sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++) {
b.Set(r.Next(32), true);
bool v = b.Get(r.Next(32));
b.Set(r.Next(32), v);
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
static long TestBoolArray(Random r, int n)
{
bool[] ba = new bool[32];
var sw = Stopwatch.StartNew();
for (int i = 0; i < n; i++) {
ba[r.Next(32)] = true;
bool v = ba[r.Next(32)];
ba[r.Next(32)] = v;
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
}