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
- Generic type is instantiated at run-time not compiled time
- Generic type are checked at time of declaration not at instantiation
- 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)
- {
-
- 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);
- list.Add(40);
- list.Add("Sixty");
- Console.WriteLine("Item Added");
- int val = (int)list[0];
- 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.
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);
- genericList.Add(20);
-
-
- Console.WriteLine("Item Added");
- int valGeneric = (int)genericList[0];
- 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. |