Collections and Generics.(Why generics are better?)

.Net platform supports two broad groups of data types value types and reference types. At times you might have to convert data from one category to another.  .NET supports a simple concept called:

Boxing:  It converts value types to reference types .
Example:
short a = 40;
object objShort = a;
In boxing CLR(Common Language Runtime) creates a new object on the heap.It copies the value(here 40) in created instance.
A reference to the new created object is returned.

image     image

Unboxing:  Exactly  reverse operation of boxing is unboxing . It converts reference types to value types.
It is mandatory that you unbox into appropriate data type. Else you get InvalidCastException.
Example:
short b = (short)objShort;   //this is ok.
int c = (int)objShort;           //this will raise an InvalidCastException.

So in order to box and unbox a simple short, CLR has to:

1) Create a new object on heap

2) Transfer value of stack based data on to that memory location

3) When unboxed,it has to transfer data back to the stack.

4) and finally Garbage collect the unused object on heap.

Although a programmer might find it easy to do boxing and unboxing operations,  if these operations are done frequently for huge collections of data , there are performance issues in speed of execution,code size and there is lack of type safety(Type safety ensures that variable or container can hold or operate only on the specified type of data).

After understanding in brief about boxing and and unboxing , let us now look into Collections and Generics and understand why generics are more better than Collections.

System.Collections namespace. 

.Net provides System.Collections namespace which contains interfaces and classes to to create dynamically sized containers.

Let us see a simple example of ArrayList , a type in System.Collections namespace.

C# code.

ArrayList arrayList = new ArrayList();
arrayList.Add(“Hello”);
arrayList.Add(34);
arrayList.Add(3.14);
arrayList.Add(new Person());

You can see that ArrayList object can be dynamically sized and there is no restriction to what the object of  ArrayList can hold. This is because  majority of types of System.Collections can hold anything ,as their members are prototyped to operate on System.Objects.

But I need a type safe container which holds data of particular type.

Say ,for example…. I want a dynamically sized container to hold data of strings only.

I will go ahead with a simple logic: Check the example.

class StringCollection
{
ArrayList arrayStringList = new ArrayList();
public void AddString(string str)
{
arrayStringList.Add(str);
}
public string GetString(int positionOfString)
{
return (string)arrayStringList[positionOfString];
}
public int Count()
{
return arrayStringList.Count;
}
}

Here StringCollection class contains an ArrayList object. I get a dynamically sized container to hold data. Then there are three methods

AddString method: To add strings to the ArrayList object
GetString method: To return strings from the ArrayList object. As members of ArrayList are protoyped to objects , to get a member’s value, unboxing is done.
Count method:  To know the count of members added to ArrayList object.

In Main Method, I am creating objects of StringCollection class  and printing the values of container to console.

class MainProgram
{
static void Main(string[] args)
{
StringCollection strCollection = new StringCollection();
strCollection.AddString("Hello");
strCollection.AddString("How are you");
strCollection.AddString("I am fine");
int count = strCollection.Count();

 

for (int i = 0; i < count; i++)
{
Console.WriteLine(strCollection.GetString(i));
}

 

Console.Read();
}
}

The above logic does serve my purpose of creating dynamically sized objects for storing data of string type.But what if I had to do similar operations or create containers for various types.

The above solution is very labor-intensive as I will have to write code for every type. And maintaining it … is very very time-consuming ,..it’s a nightmare…. Also there is an overhead of boxing and unboxing…..

Here is where Generics come into picture.

System.Collections.Generic

Generics provide:

  1. Flexible containers which are type-safe.
  2. There are no hassles of boxing and unboxing..so performance is better.
  3. You can easily create custom collections.

System.Collections.Generic namespace provides interfaces and classes to create dynamically sized generic containers. All types in this namespace have placeholders. You just have to specify the type for the placeholder.

So if I have to create a list of objects of any type .. I have a List<T> class. Here T is the type.

Example:

//This is List of integers
List<int> list = new List<int>();

 

//This is list of Strings.
List<string> listString = new List<string>();

 

//This is list for objects of Person class.
List<Person> listPeople= new List<Person>();

So  you can see how easy it is to work with generics and create containers for various types  without writing code for type-safety,boxing ,unboxing operations as it was done for collections. Thus generics are better than collections.