Pages

Thursday, June 2, 2011

Internals of Array

Arrays are most important part of your program. Almost most of the collection that you work with in .NET framework is internally maintains Array. Say for instance, if you take the List it actually internally represents T[], while Dictionary is actually an array of structure KeyValuePair internally. Hence, array forms a very important part of your program. 

Few days back while browsing over internet when I found an article written one of my buddy Dhananjay Kumar here, I thought how could I forget this important section of C# language, hence in this post, I will cover some of the important things that you need to remember while you use arrays in .NET.


Arrays Vs IEnumerables


Well, when working with Collections, the first thing that will come in your mind is the IEnumerables. Well, IEnumerable is the generic implementation of any iterators. In .NET every array internally implements an IEnuerable. You may think IEnumerable as a iterable sequence, which could be applied to anything that is iterable while array on the other hand has a fixed set of values contiguously allocated. By the way, each arrays actually implements an IEnumerable internally, so eventually in .NET every array is by default an IEnumerable.




How does an array automatically implements an IEnumerable ?

Yes, if this is in your mind, then you should read this. Actually when you declare an array the C# compiler translates it into a declaration of a class System.Array.

So, if you declare

string[] xx = { "aa" };

it is same as
Array arr = {"aa"} //even though this will produce an error

Hence, even though you think that you have declared a raw array just like what you do in Say C++, you are eventually creating an instance of a class. As this class implements IEnuerable internally, you would find the GetEnumerator inside it.

Hence you can say as any array in .NET is generally an implementation of System.Array, hence you will find few methods inside an object of it like Length, Clone, GetUpperBound, GetLowerBound etc.


How about Multi-Dimensional Arrays ?

A multi-dimensional array is also the same as Single Dimentional array and actually a System.Array inside with  a Rank of anything other than 1 (based on the number of dimensionns).
Hence

int[,] dimarray = new int[2, 3];

actually represents a multi-dimentional array. Now this is actually logically separated while you access its values.

Now when you access an element using Indexer, it will eventually divide based on Rank and get you the value. The indexer actually calls up GetValue / SetValue internally which eventually finds the actual element from the Array.

What about UpperBound and LowerBound ?

As mentioned in Dhananjay's Post, it will not be a good idea to use non-zero based lower bound for an array.  Actually even though you use non-zero lower bound, it will internally index itself using zero, but that will be hidden from you. It will actually put additional pressure while identifying the actual index when you call the indexer.

Please Note : 
Another important thing that I need to address, internally arrays are unsafe in .NET. Say for instance,

[SecuritySafeCritical]
public unsafe object GetValue(int index)
{
    if (this.Rank != 1)
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_Need1DArray"));
    }
    TypedReference reference = new TypedReference();
    this.InternalGetReference((void*) &reference, 1, &index);
    return TypedReference.InternalToObject((void*) &reference);
}

The above code is responsible for GetValue. It uses TypedReference  to get the reference of the object located in the index. The (void *) is the normal generic pointer which can point to any type of object.


What about other collections ? 

As you can see, Arrays are the basic structure of the language and each array is internally a representation of System.Array, but still there are other collections. Let me at a glance take a look at most important collections that you often require.

1. ArrayList  : Well, this is actually an extension to Array, which allows you to produce a single dimentional array of objects. Hence if you are looking to store integers inside the ArrayList, it will eventually box itself internally into object and unbox when it is fetched. This collection should be avoided, rather List is preferred. 

2. List : This is most commonly used Collection object, which implements most of the things that we require during the usage of a collection, like Sort, RemoveAll, RemoveAt etc. which are basically a part of ICollection. For the most basic usage of Collection, it is recommended to use List. Internally it holds T[] or Array of T. 

3. Dictionary : Dictionary is basically used when we need to have Key value pair for each individual object. This is actually a generic implementation of legacy HashTable. This holds an array of KeyValuePair objects.

4. HashSet : If you are looking for a collection which only needs Distinct elements, you can use HashSet. Hashset actually checks every time you are going to insert an element on it, so it is better to avoid it when you don't require.

5. ReadonlyCollection : This collection holds another collection inside it but exposes it as Readonly (hence cannot be modified). The underlying reference of IList when updated, it will automatically reflect the Readonly Wrapper collection. 

Remember, when you expose a ReadonlyCollection, that does not mean the objects inside the collection is not modifiable, but only the collection cannot.

6. ObservableCollection : This is one collection which generates automatic notifications when something is modified in it. This is very specific to its requirement when you need INotifyCollectionChanged to be implemented inside your collection.

Even though there are quite a few others, you should read its documentation before actually using it.

I hope you like my post. Feel free to write me.

Read the entire series from Here.

Thanks for reading.

No comments:

Post a Comment

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.