|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Contents
IntroductionFor quite sometime now, I am involved in the development of application software using the .NET Framework version 1.1. But there was one thing that .NET 1.1 really lacked. The support for something like 'Templates' found in the good old(?) C++. The support for the concept of type parameters, which makes it possible to design classes which take in a generic type and determine the actual type later on. This means that by using a generic type parameter My dear friends let me introduce you to the concept of 'Generics', which is included in .NET Framework version 2.0, and which can be considered very close to Templates in C++. Version 2.0 of the .NET Framework introduces a new namespace viz. Advantages of GenericsIn the earlier versions, before .NET 2.0, generalization was accomplished by casting types to and from the universal base type // The .NET Framework 1.1 way of creating a list
ArrayList list1 = new ArrayList();
list1.Add(3);
list1.Add(105);
//...
ArrayList list2 = new ArrayList();
list2.Add("First item.");
list2.Add("Second item");
//...
But this convenience comes at a cost. Any reference or value type that is added to an So, what we need is, flexibility of the In the generic // The .NET Framework 2.0 way of creating a list
List<int> list1 = new List<int>();
list1.Add(3); // No boxing, no casting
list1.Add("First item"); // Compile-time error
For the client code, the only added syntax with Generic ClassesGeneric classes encapsulate operations that are not specific to any particular data type. The most common use for generic classes is with the collections like linked lists, hash tables, stacks, queues, trees and so on where operations such as adding and removing items from the collection are performed in more or less the same way regardless of the type of the data being stored. public class Node <T>
{
T head;
T next;
}
Here, This class can be instantiated like this: Node<string> node = new Node<string>();
This will tell the compiler that the properties, head and next are of type Generic MethodsA generic method is a method that is declared with a type parameter. void Swap<T>( ref T left, ref T right)
{
T temp;
temp = left;
left = right;
right = temp;
}
The following code example shows how to call the above method: int a = 1;
int b = 2;
Swap <int> (a, b);
You can also omit the type parameter because the compiler will automatically identify it for you. The following is also a valid call to the same method: Swap (a, b);
Write your own Generic classThe following example demonstrates how you can write your own generic classes. The example shown below is a simple generic linked list class for demonstration purpose: using System;
using System.Collections.Generic;
public class MyList<T> //type parameter T in angle brackets
{
private Node head;
// The nested class is also generic on T.
private class Node
{
private Node next;
//T as private member data type:
private T data;
//T used in non-generic constructor:
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
//T as return type of property:
public T Data
{
get { return data; }
set { data = value; }
}
}
public MyList()
{
head = null;
}
//T as method parameter type:
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
Notice the declaration of the above class : public class MyList<T>
The following code example shows how the client code uses the generic class Program
{
static void Main(string[] args)
{
//int is the type argument.
MyList<int> list = new MyList<int>();
for (int x = 0; x < 10; x++)
list.AddHead(x);
foreach (int i in list)
Console.WriteLine(i);
Console.WriteLine("Done");
}
}
Okay. I think you have got a hang of the generics by now, right? Anybody who has worked with templates in C++ would find this almost similar. How generics are handled by the .NET runtimeWhen a generic type or method is compiled into MSIL, it contains metadata that identifies it as having type parameters. How this MSIL which contains generic type is used is different based on whether or not the supplied type parameter is a value or reference type. When a generic type is first constructed with a value type as parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate places in the MSIL. Specialized generic types are created once for each of the unique value type used as parameter. For example, suppose your program code declared a Stack<int> stack;
At this point, the runtime generates a specialized version of the Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();
However, if at another point in your program code another Generics work a bit differently for reference types. The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type with the object references substituted for the parameters in the MSIL. Then, each time a constructed type is instantiated with a reference type as its parameter, regardless of its type, the runtime reuses the previously created specialized version of the generic type. This is possible because all references are the same size. For example, suppose you had two reference types, a Stack<Customer> customers;
At this point, the runtime generates a specialized version of the Stack<Order> orders = new Stack<Order>();
Unlike the value types, another specialized version of the customers = new Stack<Customer>();
As with the previous use of the How does C# generics differ from C++ templatesC# Generics and C++ templates are both language features that provide support for parameterized types. However, there are many differences between the two. At the syntax level, the C# generics are a simpler approach to parameterized types without any of the complexities of C++ templates. In addition, C# does not attempt to provide all the functionality that C++ templates provide. At the implementation level, the primary difference is that the C# generic type substitutions are performed at runtime and generic type information is preserved for the instantiated objects. ConclusionGenerics are a great way of writing classes that combine reusability, type safety and efficiency. Generics are commonly used with collections. .NET 2.0 has introduced a new namespace called
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||