Generics is
one of the new concepts introduced in Dotnet 2.0. Generics are not new to
programming world. But for Dotnet it�s introduced now with a bang. The basic
idea behind generics is to develop universal classes and methods that can
accept a type as a parameter to promote reusability, efficiency and
maintainability of code.
According to MSDN, "Generics
introduce to the .NET Framework the concept of type parameters, which make it
possible to design classes and methods that defer the specification of one or
more types until the class or method is declared and instantiated by client
code." By using Generics, classes and methods can work uniformly on the
values of different types.
�
Namespace
Generics are defined with left and
right brackets: <T>. The T in <T> is simply a name that describes
the type that is going to be used. T is the standard name used to define a
generic type in most of Microsoft's documentation. The namespace to be referred
to use generics is System.Collections.Generic. Generic classes increase
performance rather than Boxing and Unboxing items using ArrayLists. Moreover
generics are type-safe.
�
Basics
��������� Generics
can be used to create classes, delegates, Methods, Interfaces.
Example 1
���������
��������� //� Generic Class
public class
GenericTestClass<T> { }
��������� // Generic
Method
������� public void
GenericTestMethod<T>(T type) { }
// Genectic Collection Class
����� List<string> myStr = new
List<string>();
The
Basic method to create and Use an inbuilt Generic collection class
Example 2
����������� // Basic Usage
����������� List<int> myInt= new List<int>();
����������� myInt.Add(1);
����������� myInt.Add(2);
����������� foreach (int mInt in myInt)
����������� {
��������������� Console.WriteLine(mInt);
����������� }
Generics
ArrayList is a highly convenient collection
class that can be used without modification to store any reference or value
type. But the main issue with Arraylist is it�s not type safe and at the same
time it casts every thing to object. This can be very well explained with the
following example. The Arraylist accepts both integer and string but at the
time of retrieval casting would be a problem.
ArrayList list = new ArrayList(); //in System.Collections
list.Add(2); // Add� Integer
list.Add("Ashok Raja"); //Add
string
int Total = 0;
�����������
��� foreach (object x in list)
��� {
���� Total += (int)x; // Raises InvalidCastexecption on Runtime.
��� }
This issue can be addressed with
the help of generic List<T> class. The generic List class is used to
create type-safe ordered list of objects. The list class enables to add items,
retrieve items with indexer, iteration with foreach.
We shall repeat the same sample with generic List class.
List<int>
intList = new List<int>();
intList.Add(1); // Add items
intList.Add(2);
intList.Add(3);
intList.Add("Ashok Raja"); //
Raises an compile time error
�����������
int number = intList[0]; // Locate with indexer
foreach (int
i in intList)
� {
� ����� Console.WriteLine(i); // No
boxing and Unboxing
� }
Generic types are types that take other type names to
define them as a type. Instead of creating a collection that is strongly typed
to a specific type, let's write a quick collection that can use any type.
public class
testList<T> : ICollection,
IEnumerable
��� {
� ������private ArrayList
_childList = new ArrayList();
������� public void Add(T val)
������� {
����������� _ childList.Add(val);
������� }
������� public T this[int index]
������� {
����������� get{return (T)_ childList [index];}
������� }
������� #region ICollection Members
������� // ...
������� #endregion
������� #region IEnumerable Members
������� // ...
������� #endregion
��� }
We can use this class to create collections that are
strongly typed to any valid .NET type, as shown in the following example.
� ��� ����� testList<int> intList = new
testList<int>();
����������� intList.Add(1);
����������� intList.Add("4");
//won't compile.
����������� testList<String> stringList = new
testList<String>();
����������� stringList.Add("1");
����������� stringList.Add(2); //won't
compile.
In C# numbers doesn�t accept null
but Generics enables us to make this possible. Let�s consider a situation that
we are assigning a value from database, to an integer variable. If the value is
a null a runtime error will be
raised. It�s because integer is a value type. This situation can be easily
solved with Nullable generic class. To have an integer to accept null it can be
declared in either one of the ways.
Declaration:
��������� Nullable<int>
x;
����� int? y;
Usage:
��������� x = 5;
����� x = null;
����� y = 7;
����� y = null;
With the help of generics dealing
with a segment of array is also a simple task. Arraysegment represents a
segment of array. It can be used to represent a portion of array.
� int[] iArray ={ 2, 4, 6, 8, 10,
12, 14, 16, 18, 20 };
//contains value 8 and 10
� ArraySegment<int> iSeg = new ArraySegment<int>(iArray,
3, 2);
for
(int i = iSeg.Offset; i < iSeg.Offset +
iSeg.Count; i++)
���� ����� {
������ ���� ����� MessageBox.Show(iSeg.Array[i].ToString());
��� � ����� }
Constraints
Constraints can be used in
Generics to restrict the way the types are used in Classes and are enabled by
adding the keyword where next to the
type parameter.
Generics support four types of Constraints
1.
Interface
2.
Base
Class
3.
Constructor
4.
Reference
or Value Type
Example 3
���������
��������� This
example shows how a class can be restricted to use a type, which has already
implemented IDisposable.
//Generic class
created with a IDisposable constraint
//Instantiation
of this class acepts only Types with IDisposable //implementation
��� public class
testClass<T> where
T : IDisposable
��� {
������� // Class Methods .......
��� }
The above class can be instantiated as
�//will compile since Form� has implementation of IDisposable
� testClass<Form> tClass = new
testClass<Form>();
//Error on compilation, string is a type without implementation of
IDisposable
� testClass<string> tClass = new
testClass<string>();
� Default Value
A generic type cannot be assigned null. The reason behind this is a
generic type can be instantiated as a value type or a reference type.� The default value for a value type is zero
and the default value type for a reference type is null.
Example 4
��� public class genTestDefault<T>
��� {
������� public� T GetDefault()
������� {
����� ����� //Error on compilation
��� ��������return null;
����� ����������
������� }
��� }
To overcome this issue,
default keyword can be used. default
returns 0 if the type is a value type and null if the type is a reference type.
Example 5
��� public class genTestDefault<T>
��� {
������� public� T GetDefault()
������� {
���������� // Returns 0 if it's value
type and null if a reference type
����������� return default(T);
������� }
���
}
Existing Collection Types and its Equivalent Generic Types
S.No
|
Collection Type
|
Generic Type
|
|
1
|
ArrayList
|
List
|
|
2
|
Hashtable
|
Dictionary
|
|
3
|
CollectionBase
|
Collection ( not abstract as CollectionBase)
|
|
4
|
ReadOnlyCollectionBase
|
ReadOnlyCollection
|
The Queue, Stack, and SortedList
generic classes correspond to the respective nongeneric classes with the same
names.
There are several generic collection types that do not
have nongeneric counterparts.
LinkedList , SortedDictionary, KeyedCollection are generic
collection types that do not have nongeneric counterparts.
Conclusion
��������� Before
DotNet 2.0, Interfaces IList, ICollection, IEnumerable, IDictionary are used to
create type safe collection. Now it�s preferable to use generic collections if
the requirement is a type safe collection.
References
1.
http://research.microsoft.com/projects/clrgen/
2.
http://msdn2.microsoft.com/en-us/library/512aeb7t.aspx