In this article, we are going to learn about BitArray class in C#, how to create an instance of it, and what its properties and methods are.

We’re also going to learn about the difference between BitArray and bool array.

To download the source code for this article, you can visit our GitHub repository.

Let’s start.

What Is a BitArray in C#?

BitArray class is a type that manages an array of bits. Every bit is represented as a boolean value where the value is true if the bit is on and false if the bit is off.

BitArray implements ICollection and ICloneable interfaces.

Don't like the ads? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!

How to Create a BitArray in C#?

BitArray class has six constructors that we can use to create a new instance.

BitArray(Int32)

With this constructor, we can initialize a new instance with a specified number of bit values:

BitArray bitArray1 = new BitArray(8);
bitArray1.Print();  // False False False False False False False False

The default value is False.

As you can see, we use the Print extension method to loop and print elements of BitArray:

public static void Print(this BitArray bitArray)
{
    foreach (bool bit in bitArray)
    {
        Console.Write(bit + " ");
    }
    Console.WriteLine();
}

BitArray(Int32, Boolean)

We use this constructor to initialize a new instance with a specified number of bit values and set these values:

BitArray bitArray2 = new BitArray(8, true);
bitArray2.Print(); // True True True True True True True True

BitArray(Byte[])

With this constructor, we can initialize a new instance that contains bit values copied from the specified array of bytes:

BitArray bitArray3 = new BitArray(new byte[1] { 2 });
bitArray3.Print(); // False True False False False False False False

We know that one byte equals 8 bits, i.e the value 2 converts to 01000000, so the second bit is on (True) and the other bits are off (False).

BitArray(Int32[])

Using this constructor, we can initialize a new instance that contains bit values copied from the specified array of 32-bit integers:

BitArray bitArray4 = new BitArray(new int[1] { 4 });
bitArray4.Print(); // False False True False False False ...

The value 4 converts to 32 bits: 00100000 00000000 00000000 00000000, so the third bit is on (True) and the other bits are off (False).

BitArray(Boolean[])

If we have an array of booleans that we want to convert to a bit array, we can use this constructor:

BitArray bitArray5 = new BitArray(new bool[8]); 
bitArray5.Print(); // False False False False False False False False

Although that boolean type takes 8 bits, every value of the boolean array maps to a single value in BitArray.

BitArray(BitArray)

With this constructor, we can initialize a new instance that contains bit values copied from the specified BitArray:

BitArray bitArray6 = new BitArray(bitArray1);
bitArray6.Print(); // False False False False False False False False

BitArray Properties in C#

Let’s explore the properties of BitArray and what we can do with them.

Count Property

It enables us to get the number of items in the BitArray:

BitArray bitArray = new BitArray(8);
Console.WriteLine(bitArray.Count); // 8

IsReadOnly Property

We use this property to get a value that specifies whether the BitArray is read-only:

Console.WriteLine(bitArray.IsReadOnly); // False

This property is required by the ICollection interface and it’s always false.

IsSynchronized Property

It enables us to get a value that specifies whether access to the BitArray is synchronized:

Console.WriteLine(bitArray.IsSynchronized); // False

Same as the previous one, this one is required by the ICollection interface and it’s always false.

Indexer

In situations where we want to get or set the value of the bit at a specific index in BitArray, we can use indexer:

bitArray[0] = true;
Console.WriteLine(bitArray[0]); // True

Length Property

With this property, we can get or set the number of items in the BitArray:

Console.WriteLine(bitArray.Length); // 8
bitArray.Length = 6;
Console.WriteLine(bitArray.Length); // 6

This property returns the same value that the Count property returns, but it can be set to a specific value. On the other hand, the Count property is read-only.

SyncRoot Property

It enables us to get an object that can be used to synchronize access to the BitArray:

lock(bitArray.SyncRoot)
{
    foreach (var item in bitArray)
    {
        // Insert your code here.
    }
}

BitArray Methods in C#

Let’s explore the main methods of BitArray and what we can do with them.

Get(Int32)

With this method, we can get the value of the bit at a specific index in the BitArray:

Console.WriteLine(bitArray.Get(0)); // Equal: Console.WriteLine(bitArray[0]);

Set(Int32, Boolean)

We use this method to set the value of the bit at a specific index in aBitArray:

bitArray.Set(0, true); // Equal: bitArray[0] = true;

SetAll(Boolean)

If we need to set all bits to the specified value, we can use this method:

bitArray.SetAll(true);
bitArray.Print(); // True True True True True True True True

Logical Methods

BitArray class provides us with many logical operations such as: And, Or, Xor, Not, LeftShift, and RightShift:

BitArray bitArray1 = new BitArray(new bool[] { false, false, true, true });
BitArray bitArray2 = new BitArray(new bool[] { false, true, true, false });

bitArray1.And(bitArray2).Print(); // False False True False
// bitArray1 : { False False True False }
 
bitArray1.Or(bitArray2).Print();  // False True True False
// bitArray1 : { False True True False }
bitArray1.Xor(bitArray2).Print(); // False False False False
// bitArray1 : { False False False False }
bitArray2.LeftShift(1).Print();   // False False True True
// bitArray2 : { False False True True }
bitArray2.RightShift(1).Print();  // False True True False

First, we use the And method to apply the And operation between two BitArray objects: bitArray1 and bitArray2. The And method returns true if both bits are true, otherwise, the result is false. So in the result, the third bit is true and the other bits are false. It also modifies bitArray1 with the result and returns it.

Secondly, we use the Or method. This method returns false if both bits are false, otherwise, the result is true, so the bitArray1 become False True True False.

Next, we apply the Xor method that returns false if both bits are the same, otherwise, the result is true. As we can see bitArray1 becomes False False False False.

Then, we use the LeftShift method on bitArray2 object. As the name suggests, this method shifts the bits to the left and the empty places become false.

Finally, we use the RightShift method on bitArray2 object. This method shifts the bits to the right, and also the empty places become false.

BitArray vs Bool [] in C#

As we saw, BitArray class looks similar to bool[], but which one should we use?

To answer this question, let’s introduce the BenchmarkDotNet library to compare them:

[MemoryDiagnoser(false)]
public class BitArrayBenchmark
{
    [Params(100, 1000_000, 100_000_000)]
    public int Size { get; set; }

    [Benchmark]
    public void BitArray()
    {
        BitArray bitArray = new BitArray(Size);
        for (int i = 0; i < bitArray.Length; i++)
        {
            bitArray[i] = true;
        }
    }

    [Benchmark]
    public void BoolArray()
    {
        bool[] boolArray = new bool[Size];
        for (int i = 0; i < boolArray.Length; i++)
        {
            boolArray[i] = true;
        }
    }
}

After running the benchmark we can inspect the results:

|    Method |      Size |             Mean |           Error |          StdDev |   Allocated |
|---------- |---------- |-----------------:|----------------:|----------------:|------------:|
|  BitArray |      1000 |       1,580.3 ns |        29.85 ns |        24.93 ns |       184 B |
| BoolArray |      1000 |         381.0 ns |         7.39 ns |        10.36 ns |      1024 B |
|  BitArray |   1000000 |   1,598,289.9 ns |    11,505.53 ns |     9,607.64 ns |    125069 B |
| BoolArray |   1000000 |     819,307.9 ns |    11,237.79 ns |     9,962.01 ns |   1000108 B |
|  BitArray | 100000000 | 157,092,742.3 ns | 2,070,604.76 ns | 1,729,048.75 ns |  12500332 B |
| BoolArray | 100000000 |  43,521,267.5 ns |   777,912.09 ns |   864,647.22 ns | 100000373 B |

We notice that BitArray is memory efficient over bool[], because in BitArray, we need 1 bit to store a value, but in the bool[] we need 8 bits. This means that bool[] needs x8 more memory than BitArray. 

On the other hand, bool[] is faster than BitArray. This is because of how the values are stored in BitArray. They are stored inside an array of 32-bit integers. This means doing some processing when setting or getting a value, and this takes more CPU cycles.

Therefore, the decision on which one to use really depends on what we need.

Conclusion

In this article, we’ve learned about the BitArray class in C#, and what its constructors, properties, and methods are. We’ve also compared between BitArray and bool[].

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!