How to manipulate BitArrays

Samuel

New member
Joined
Apr 14, 2019
Messages
3
Programming Experience
Beginner
This is my first post here. I am trying to learn C#, and have no development experience. I found the code below and can not follow what is going on in the sections I have labeled.
BitArray implementation of Indexers:
class BitArray
{
    int[] bits;
    int length;

    public BitArray(int length) {
        if (length < 0) throw new ArgumentException();
        bits = new int[((length - 1) >> 5) + 1];
        this.length = length;
    }

    public int Length {
        get { return length; }
    }

    public bool this[int index] {
        get {
            if (index < 0 || index >= length) {
                throw new IndexOutOfRangeException();
            }//What is happening in the line below?
            return (bits[index >> 5] & 1 << index) != 0;
        }
        set {
            if (index < 0 || index >= length) {
                throw new IndexOutOfRangeException();
            }// Also in the if statement below I do not see what is going on
            if (value) {
                bits[index >> 5] |= 1 << index;
            }// Same here in the else block, what is happening?
            else {
                bits[index >> 5] &= ~(1 << index);
            }
        }
    }
}
I got the code from here.
 
Why are you even looking at that code in the first place? What are you actually trying to achieve?
I am reading the C# via CLR book by Jeff Richer. On page 622 he has the following code:
C#:
[Serializable]
public class Dictionary<TKey, TValue>: ISerializable, IDeserializationCallback {
// Private fields go here (not shown)
private SerializationInfo m_siInfo; // Only used for deserialization
// Special constructor (required by ISerializable) to control deserialization
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
protected Dictionary(SerializationInfo info, StreamingContext context) {
// During deserialization, save the SerializationInfo for OnDeserialization
m_siInfo = info;
}
// Method to control serialization
[SecurityCritical]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("Version", m_version);
info.AddValue("Comparer", m_comparer, typeof(IEqualityComparer<TKey>));
info.AddValue("HashSize", (m_ buckets == null) ? 0 : m_buckets.Length);
if (m_buckets != null) {
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[Count];
CopyTo(array, 0);
info.AddValue("KeyValuePairs", array, typeof(KeyValuePair<TKey, TValue>[]));
}
}
// Method called after all key/value objects have been deserialized
public virtual void IDeserializationCallback.OnDeserialization(Object sender) {
if (m_siInfo == null) return; // Never set, return
Int32 num = m_siInfo.GetInt32("Version");
Int32 num2 = m_siInfo.GetInt32("HashSize");
m_comparer = (IEqualityComparer<TKey>)
m_siInfo.GetValue("Comparer", typeof(IEqualityComparer<TKey>));
if (num2 != 0) {
m_buckets = new Int32[num2];
for (Int32 i = 0; i < m_buckets.Length; i++) m_buckets[i] = -1;
m_entries = new Entry<TKey, TValue>[num2];
m_freeList = -1;
KeyValuePair<TKey, TValue>[] pairArray = (KeyValuePair<TKey, TValue>[])
m_siInfo.GetValue("KeyValuePairs", typeof(KeyValuePair<TKey, TValue>[]));
if (pairArray == null)
ThrowHelper.ThrowSerializationException(
ExceptionResource.Serialization_MissingKeys);
for (Int32 j = 0; j < pairArray.Length; j++) {
if (pairArray[j].Key == null)
ThrowHelper.ThrowSerializationException(
ExceptionResource.Serialization_NullKey);
Insert(pairArray[j].Key, pairArray[j].Value, true);
}
} else { m_buckets = null; }
m_version = num;
m_siInfo = null;
}
While I get the point he tried to make, I can not follow what is going on every line. So I started looking up the parts I did not get. The first one was Dictionary<TKey, TValue>, and I could not follow how Indexers worked, so I looked up indexer specification which gave an example of indexers are used in BitArrays, and I think that is how I found the language reference. If I understand Indexers well, I think I would be all set. I just need an explanation that does not involve shift to left or right operations I guess. For instance the code below they use "this" keyword to refer to the indexer, and I have never seen "[]"s used for a member field before.
C#:
using System;

class SampleCollection<T>
{
   // Declare an array to store the data elements.
   private T[] arr = new T[100];

   // Define the indexer to allow client code to use [] notation.
   public T this[int i]
   {
      get { return arr[i]; }
      set { arr[i] = value; }
   }
}

class Program
{
   static void Main()
   {
      var stringCollection = new SampleCollection<string>();
      stringCollection[0] = "Hello, World";
      Console.WriteLine(stringCollection[0]);
   }
}
// The example displays the following output:
//       Hello, World.
I have to say reading through the language specification helped me with some gaps in what I knew about C# class. For instance, I did not understand properties well and how accessors worked, but I feel a lot better about it now. Why is that not a good read for someone like me? Would you elaborate please?
 
Why is that not a good read for someone like me?
I didn't say that it wasn't. You seem to be assuming that there was some nefarious intent in my question. There wasn't. It was a question intended to elicit information that could help me better answer your question. As it turns out, it was a good idea because it seems that the question you asked is not really the question you want answered. If you want to know about indexers then it's probably a good idea to ask about indexers.

Anyway, and indexer in a C# class is basically a special property that allows you to access data within the class by index. The brackets notation is how you specify an index in C#. If you have ever used arrays then you would be familiar with that, e.g.
C#:
// Create a new array with 12 elements.
var squares = new int[12] {};

// Set each element.
for (var i = 0; i < numbers.Length; i++)
{
    squares[i] = i * i;
}

// Display each element.
for (var i = 0; i < numbers.Length; i++)
{
    Console.WriteLine(squares[i]);
}
Just as you index an array using brackets, so you index a class with an indexer using brackets. The SampleCollection class in your last code snippet could be used in virtually the same way.

The indexer itself is pretty much like a regular property, with a getter and setter. It is always named this though, and it can have one or more parameters, just like a method. As you noticed though, those parameters are specified within brackets rather than parentheses though. More often than not, an index would be a sequential numeric value, as for an array. They could be something else though, e.g. an arbitrary string key or other object, as for a Dictionary. A Dictionary is something like an array in that it contains multiple values, but those values are identified by their relationship to unique key values rather than a sequential numerical order.
 
Thank you so much. You are right, I am defensive without realizing that I do that. Thanks for clarification, and thank you so much for taking the time to explain the topic. As you know some forums are a bit stringent on what people ask, and the format and whether they have researched the topic. This helped me realize I should be more patient and provide the requested details without assuming. Greatly appreciate your response.
 
Back
Top Bottom