Explanation:
Generics are considered
an advanced and powerful idiom in any language. When I first encountered templates
in C++, they seemed a little confusing. Then I read Bjarne Stroustrop's The Design
and Evolution of C++, and templates seemed as easy to use as the C macros and simple
string-replacement templates they supplanted. Templates and generics are the same
thing—though their implementations are slightly different.
Generics in C# support defining algorithms and deferring the data type until the
point of use. In early versions of C#, we arguably could live without generics because
every type was derived from a common base type: object. This meant that
programmers could define a Stack class based on the object type
and put anything in the Stack (because everything's earliest ancestry is
an object). However, a Stack of objects meant that Customer
objects, Integer objects, and Foo objects
could all be placed in the same Stack instance. The result was that developers
subclassed data types to tighten up the type of data with which they interacted.
For example, when writing custom business objects, it was a recommended practice
to define strongly typed collections derived from System.Collections.CollectionBase.
The reason is simple: Defining everything based on objects is considered weak typing.
Generics in C# support some additional refinements. For example, a method or class
can have more than one parameterized type, and generics in C# support WHERE
constraints that refine the type of the parameterized types. For example, if a generic
type must implement IDisposable, C# generics support expressing this limitation.
If you explore System.Collections.Generic namespace
there are several generic data structures that support typed collections, hashes,
queues, stacks, dictionaries, and linked lists. To use these powerful data structures,
all you have to do is provide the data type.
Here we look at very simple example of using Generic Collection;
using System;
using System.Collections.Generic;
using System.Text;
namespace Generics
{
class Program
{
static void Main(string[] args)
{
List<Customer>
customers = new List<Customer>();
customers.Add(new Customer("Motown-Jobs"));
customers.Add(new Customer("Fatman's"));
foreach (Customer c
in customers)
Console.WriteLine(c.CustomerName);
Console.ReadLine();
}
}
public class Customer
{
private string customerName = "";
public string CustomerName
{
get { return customerName;
}
set { customerName
= value; }
}
public Customer(string customerName)
{
this.customerName =
customerName;
}
}
}
Here we have a strongly typed collection—List<Customer>—without writing
a single line of code for the collection class itself. If we wanted to extend the
customer list, we could derive a new class by inheriting from List<Customer>.
Implementing Genaric Classes;
Now, we can define our own Generic class and later we will implement it by simple
example:
// type parameter T in angle brackets
public class GenericList<T>
{
// The nested class is also generic on T
private class
Node
{
// T used in non-generic constructor
public Node(T t)
{
next = null;
data = t;
}
private Node next;
public Node Next
{
get {
return next; }
set {
next = value; }
}
// T as private member data type
private T data;
// T as return type of property
public T Data
{
get {
return data; }
set {
data = value; }
}
}
private Node head;
// constructor
public GenericList()
{
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;
}
}
}
The following code example shows how client code uses the generic GenericList<T>
class to create a list of integers. Simply by changing the type argument, the code
below could easily be modified to create lists of strings or any other custom type:
class TestGenericList
{
static
void Main()
{
// int is the type argument
GenericList<int>
list = new GenericList<int>();
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
foreach (int i
in list)
{
System.Console.Write(i + " ");
}
System.Console.WriteLine("\nDone");
}
}
|