Generic Types
Generics are the most powerful feature of C# 2.0. It allows defining type-safe data structures, without committing to actual data types. In C# 1.0 we can either declare reference type or value type. But in most of the application we come across situation where we need type that can hold both reference & value type. In such situation we use generic types.
Why Generics?
-
Generic type doesn't care what the type is. We can specify the type at runtime.
-
It avoids boxing difficulties. In C# 1.0, if we want to put any object into a List, Stack, or Queue objects, we have to take type as System.Object.
-
It boosts the performance of the application because we can reuse data processing algorithm without duplicating type-specific code.
How Generic implemented:
(1) Generic type is instantiated at run-time not compiled time
(2) Generic type are checked at time of declaration not at instantiation
(3) It works for both reference type & value type.
Let's create simple class "GenericList" using C# 1.0 & 2.0 respectively & compare them.
Code GenericList Class (C# 1.0)
using System;
using System.Collections.Generic;
using System.Text;
public class GenericList
{
private object[] elements;
private int count;
public GenericList()
{
elements = new object[10];
}
public object this[int index]
{
get { return elements[index]; }
set { elements[index] = value; }
}
public void Add (object parm)
{
if (count == elements.Length)
{
// Increase the
object[] tmpArray = null ;
elements.CopyTo(tmpArray,0);
elements = new object[count * 2];
elements = tmpArray;
}
elements[count] = parm;
count = count + 1;
}
}
Main Method:
static void Main(string[] args)
{
Console.WriteLine("using C# 1.0");
GenericList list = new GenericList();
list.Add(20); //Argument is boxed
list.Add(40); //Argument is boxed
list.Add("Sixty"); //Error in retrieving
Console.WriteLine("Item Added");
int val = (int)list[0]; //Casting required
Console.WriteLine("Value retrived : " + val);
}
Memory Consumption
In C# 1.0 boxing is necessary evil to make type system work. While working with structures of System.Collection namespace (Stacks,List,Hashtable etc) we face the problem in insertion & retrieval of values. We need to take System.object as type & System.object is reference type, so whenever we access the hashtable, the runtime has to box the values to put into the collection & need to unbox to take it out.
list.Add(20); //Argument is boxed
In C# int takes 4 byte but when it boxed it take (4+8) 12 bytes, which is 3 times to normal size.
In C# 2.0 the type is decided at runtime so boxing does not take place.
Type Safe
When we use the statement
list.Add ("Sixty"); or List [3] = "sixty";
It compiles successfully but later on if some one pulls value and cast it into integer it fails. The problem is fixed in C# 2.0; we will get compilation error there.
Code GenericList Class (C# 2.0)
public class GenericList<T>
{
public GenericList()
{
elements = new T[10];
}
private T[] elements;
private int count;
public T this[int index]
{
get {return elements [index];}
set {elements [index] = value;}
}
public void Add (T parm)
{
if (count == elements.Length)
{
T[] tmpArray = null;
elements.CopyTo(tmpArray, 0);
elements = new T [count * 2];
elements = tmpArray;
}
elements [count] = parm;
count = count + 1;
}
}
Main Method:
static void Main(string[] args)
{
Console.WriteLine("using C# 1.0");
GenericList<int> genericList = new GenericList<int>();
genericList.Add (10); //No boxing
genericList.Add (20); //No boxing
// genericList.Add("Fifty"); //Compile Time Error
Console.WriteLine("Item Added");
int valGeneric = (int)genericList[0]; //No Casting Required
Console.WriteLine("Value retrived : " + valGeneric);
}
Some other Points:
(1) Type parameter can be applied to Class, struct, interface & delegates.
struct Buket<K, V>;
interface ICompare<T>
(2) Type parameter can have constraints.
Constraint |
Description |
Public class Books where T: struct |
The type argument for class Books must be a value type |
Public class Books where T: class |
The type argument for class Books must be a reference type |
Public class Books where T: new( ) |
The type argument for class Books must have a public default constructor |
Public class Programmer where T: <Employee> |
The type argument for class Programmer must be of Employee type. |