Collections

·         Collections are introduced in .Net 1.0
·         Earlier we were using Array as collection to store multiple values of similar type. But it has some drawbacks like:
·         Size of the Array is fixed, defined at compile time. If we want to increase the array we need to create a new array with updated (required) size and then copy the whole array into the newly created array. .Net provides a method Array.Resize() implemented in Array class, which does the same for us.
E.g.:       int[] arr = new int[10]();
                 Array.Resize(ref arr,20);
·         We cannot directly add/ remove any array element that is placed somewhere in the middle of the array. For that we need to shift all remaining element accordingly.
·         To overcome these drawbacks, we use Syste.Collections.ArrayList. We can add an element anywhere in ArrayList using arrayListObject.Insert(int index, object value) and remove any element using either arrayListObject.Remove(object obj) or arrayListObject.RemoveAt(int index). ArrayList internally increases the size as per requirement. By default it allocates memory for four (4) elements, if we add fifth (5th) element then it doubles the size i.e. 8 elements. We can set the default capacity that ArrayList initially can have, using ArrayList al = new ArrayList(10); In this case ArrayList al will be created with initial capacity 10, and when we will add the 11th element it will be increased to 20 elements.
·         ArrayList uses <key, value> pair for each element, but the index is system defined, starting from 0. If we want to have user defined keys for element then we use HashTable. It is same like ArrayList except it has user defined keys. So to add any element in HashTable we need to pass two parameters like: hashTableObject.Add(object key, object value). HashTable internally uses HashCode to store the elements, that’s why when we access the elements through loop, it does not returns the elements in a sequence as they were added. HashCodes are internally generated using GetHashCode()method of Object class which returns integer HashCode value.
·         Collections are not TypeSafe as they accepts any type of element e.g. arrayListObject.Add(object value), it will add any type of element, which can cause an issue. So we use Generics. Generics are TypeSafe collections, introduced in .Net 2.0 and come under System.Collections.Generic namespace.
·         We can create any method or class generic by adding <T> suffix.
 E.g.:    public void add<T> (T parameter1, T parameter2){}
To call this function: add<int>(10,20);    
public class MyClass<T>
                To create object of this class: MyClass<int> obj = new MyClass<int>();
Once we create object of generic class with type <T>, we don’t need t add <T> when we want to create generic method.
E.g.: public void add(T parameter1, T parameter2)
·         The generic version of ArrayList is List<T> which is similar to ArrayList except, we need to pass type while creating the object. E.g.: List<int> li = new List<int>(); This will add only integer elements.
·         The generic version of HashTable is Dictionary<TKey, TValue> Though HashTable and Dictionary are same but Dictionary doesn’t use HashCode to store the element so we will get the elements as we added.
·         Dynamic is a data type similar to Var introduced in .Net 4.0. Both are used to store any type of data, the only difference is var identifies the datatype at compile time and dynamic identifies data type at runtime. Var needs to be initialize at the time of declaration as it has to identify the data type, whereas we don’t need to initialize the value of dynamic variable.
·         Collections can be sorted by collectionObject.Sort() method. But it supports only primitive data types like int, string etc. but in case of complex data type like class, we need to explicitly write logic. Sort() method internally calls compares two object, so to compare two complex object we need to implement either IComparable or IComparer interface.
·         When we have to compare an object with the current object, then we inherits IComparable<T> interface and implements int CompareTo(T target) method.
E.g.: suppose we have to compare two students by their ID’s then:
Public class Student : IComparable<Student>
{
                Public int CompareTo(Student target){
                Return this.ID – target.ID;
                //returns 1 for positive, -1 for negative and 0 for equal
}
}
Now when we call studentCollection.Sort(), it will sort collection by ID’s.
·         When we have to compare two objects in different class, then we inherits IComparer<T> interface and implements int Compare(T source, T target) method.
E.g.: suppose we have to compare two students by their ID’s but we don’t have edit access to Student class then:
Public class CompareStudent : IComparer<Student>
{
                Public int Compare(Student source, Student target){
                Return source.ID – target.ID;
                //returns 1 for positive, -1 for negative and 0 for equal
}
}
Now in this case, we need to pass the object of CompareStudent to Sort() method as:
CompareStudent obj  =  new CompareStudent();
studentCollection.Sort(obj); so this will sort collection by ID using Compare method.