SIGN UP MEMBER LOGIN:    
ARTICLE

Generics in C# - Part II

Posted by Amr Monjid Articles | Visual C# April 11, 2008
In part II of generics in C# we will see how to create generic classes, structures, interfaces, and delegates. We will also see how to create a custom generic collections.
Reader Level:
Download Files:
 


Introduction:

Generics gives you the ability to create a generic methods or a generic type by defining a placeholder for method arguments or type definitions, which are specified at the time of invoking the generic method or creating the generic type.

Generic classes and structures

A generic class is a class that have a type parameter <T> representing the data type of the class variables.

Example:

public class MyGenericClass<T>

{

    //Generic variables

    private T d1;

    private T d2;

    private T d3;

  

    public MyGenericClass(){}

  

    //Generic constructor  

    public MyGenericClass(T a1, T a2, a3)

    {

        d1 = a1;

        d2 = a2;

        d3 = a3;

    }       

   

    //Generic properties

    public T D1

    {

        get{return d1; }

        set{d1 = value; }

    }

 

    public T D2

    {

        get{ return d2; }

        set{ d2 = value; }

    }

  

    public T D3

    {

        get{ return d3; }

        set{ d3 = value; }

    }

}
 
Assume you want a way to reset the variables in your generic class to its default values, but in fact you don't know really what is the data type that the placeholder <T> will represent, so you can't know what is the default value will be.
In generic classes you can make use of the default keyword to reset your data safely to its default value as follow:
 
d1 = default(T);
 
So whatever your type parameter will be, you can reset it safely to its default value.
 
We can add this method to our generic class:
 

public void ResetValues()

{

    d1 = default(T);

    d2 = default(T);

    d3 = default(T);

}

 

Here is our generic class in use:

 

//contain int values

MyGenericClass<int> c1 = new MyGenericClass<int>(5, 10, 15);

 

//reset values to 0

c1.ResetValues();

 

//contain string values

MyGenericClass<string> c2 = new MyGenericClass<string>("a", "b", "c");

 

//reset values to null

c2.ResetValues();


Note: you can create generic structures in the same way of creating generic classes, you only have to remove the class keyword and add struct keyword.
 

public struct MyGenericStruct<T>

{

}
 
Creating a Custom Generic Collection

Under the namespace System.Collections.Generic you will find a lot of generic collections types and may be you will not need to build a custom generic collection.
 
Building a custom generic collection allows you to build a generic collection that have your own methods and you can also constrain you generic collection to contain only the data type you want.
 
A generic collection is a generic class that implements the IEnumerable<T> generic interface. The IEnumerable<T> interface allows you to support foreach loop.
 
Example:

public class EmployeeCollection<T> : IEnumerable<T>

{

    List<T> empList = new List<T>();

   

    public void AddEmployee(T e)

    {

        empList.Add(e);

    }

 

    public T GetEmployee(int index)

    {

        return empList[index];

    }

 

    //Compile time Error

    public void PrintEmployeeData(int index)

    {

       Console.WriteLine(empList[index].EmployeeData);   

    }

 

    //foreach support

    IEnumerator<T> IEnumerable<T>.GetEnumerator()

    {

        return empList.GetEnumerator();

    }

 

    IEnumerator IEnumerable.GetEnumerator()

    {

        return empList.GetEnumerator();

    }

}

 

public class Employee

{

    string FirstName;

    string LastName;

    int Age;

   

    public Employee(){}

    public Employee(string fName, string lName, int Age)

    {

        this.Age = Age;

        this.FirstName = fName;

        this.LastName = lName;

    }

 

    public string EmployeeData

    {

        get {return String.Format("{0} {1} is {2} years old", FirstName, LastName, Age); }

    }

}
 
Constraining the type parameter of the generic collection:
 
When we try to use our Generic collection we will face some problems, let's see it and see how to solve it.
 
The first problem is that the user of the collection can use it for any data type instead of Employee:
 

EmployeeCollection<int> a = new EmployeeCollection<int>();

EmployeeCollection<string> a = new EmployeeCollection<string>();
 
The second problem will appear when you try to use the EmployeeData property of the Employee class in you generic collection, so if we add this method to our generic collection to use the EmployeeData property:
 

// Compile time Error

public void PrintEmployeeData(int index)

{

   Console.WriteLine(empList[index].EmployeeData);   

}
 
When we try to compile the generic collection we will get a compile time error because the identity of T is not known yet, and we don not know for certain if the type of the item in the List<T> has an EmployeeData property.
 
We can solve these problems by constraining the type parameter T using where as follow:


 

public class EmployeeCollection<T> : IEnumerable<T> where T : Employee

{

    //we can call EmployeeData property

    //because all items in the List<T> is Employee 

    public void PrintEmployeeData(int index)

    {

       Console.WriteLine(empList[index].EmployeeData);   

    }

}


We now can use the EmployeeData to contain only the Employee type:

 

//its OK

EmployeeCollection<Employee> a = new EmployeeCollection<Employee>();

 

//Compiler error

EmployeeCollection<int> a = new EmployeeCollection<int>();
 
There is other types of where constrain you can use:
 
Example:
 

where T : class

 

//The type parameter must be a reference type

public class MyGenericCollection<T> : IEnumerable<T> where T : class

{

    . . .

}

 

where T : struct

 

//The type parameter must be a value type

public class MyGenericCollection<T> : IEnumerable<T> where T : struct

{

    . . .

}

 

where T : new()

 

//The type parameter must have a default constructor

public class MyGenericCollection<T> : IEnumerable<T> where T : new()

{

    . . .

}

 

where T : InterfaceName 

 

//The type parameter must implement the interface

//specified by InterfaceName 

public class MyGenericCollection<T> : IEnumerable<T> where T : InterfaceName

{

    . . .

}

 

where T : ClassName

 

//The type parameter must be derived

//from the class specified by Classname

public class MyGenericCollection<T> : IEnumerable<T> where T : ClassName

{

    . . .

}
 
You can use the where constrain also with generic methods
 
Example:

//the arguments of this method must be value type

public void MyGenericMethod<T> (T x, T y) where T : struct

{

    . . .

}


Creating Generic Interfaces
 
Under the .NET 2.0 you can define generic interfaces, you can do this as follow:

public interface IMyGenericInterfce<T>

{

    void Method1(T a, T b);

    T Method2(T a, T b);

} 
 
You can use the constrains also with the generic interface:

//the type parameter must be a value type

public interface IMyGenericInterfce<T> where T : struct

{

    void Method1(T a, T b);

    T Method2(T a, T b);

}

Implementing our generic interface:

public class MyClass : IMyGenericInterfce<int>

{   

    public void Method1(int a, int b)

    {. . .}

 

    public int Method2(int a, int b)

    {. . .}

} 

Creating Generic Delegates
 
Under the .NET 2.0 you can define generic delegates, you can do this as follow:

//this delegate can call any method that return void

//and takes two parameters

public delegate void MyGenericDelegate<T>(T a, T b); 

Using our generic delegate:
 

MyGenericDelegate<int> myDel1 = new MyGenericDelegate<int>(MyTargetMethod1);

 

myDel1(5, 10);

 

MyGenericDelegate<string> myDel2 = new MyGenericDelegate<string>(MyTargetMethod2);

 

myDel2("a", "b");

 

public static void MyTargetMethod1(int x, int y)

{. . .}

 

public static void MyTargetMethod2(string x, string y)

{. . .}


I hope you know have a good idea about creating and using generic types.

Part I - Part II

Login to add your contents and source code to this article
share this article :
post comment
 

Till now,generic was some unknown demon for me,Thanks to this article,I am confident in facing any question in interview related to generics. Thank you very much Amr Monjid! God bless you!

Posted by avishek chowdhury Dec 21, 2011

Hi Amr Monjid , It is a good article to understand the Generics i.e parametric polymorphism .. I am facing some problems with the below program which I wrote .. please go through it and reply me .. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace GenericExam2 { class simple<T> { public T Add(T a, T b) { T c; c = a + b; return c; } public T Mult(T a, T b) { T c = a * b; return c; } public T Add(T a, T b, T c) { T d = a + b + c; return d; } } class Program { static void Main(string[] args) { simple<int> s1 = new simple<int>(); simple<double> s2 = new simple<double>(); int i1 = s1.Add(10, 20); double d1 = s2.Add(10.5, 10.5); int i2 = s1.Add(10, 20, 30); double d2 = s2.Add(3.5, 3.5, 3.5); int i3 = s1.Mult(10, 20); double d3 = s2.Mult(2.5, 2.5); Console.WriteLine(" \n Addition of two integers : {0}", i1); Console.WriteLine(" \n Addition of three integers : {0}", i2); Console.WriteLine(" \n Muliplication of two integers : {0}", i3); Console.WriteLine(" \n Addition of two doubles : {0}", d1); Console.WriteLine(" \n Addition of three doubles : {0}", d2); Console.WriteLine(" \n Muliplication of two doubles : {0}", d3); Console.ReadLine(); } } } Please check the above program and reply me sir .... Thanking you, Shankar Reshmimath

Posted by Shankar Reshmimath Mar 08, 2011

It is a vry good post and it vry useful who are beginners of generics

Posted by Ashwini varma Dec 08, 2010

thanks of  your  of your help

Posted by mohammad hassan mohammadi Oct 07, 2010
6 Months Free & No Setup Fees ASP.NET Hosting!
Become a Sponsor
PREMIUM SPONSORS
  • ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
    Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Team Foundation Server Hosting
Become a Sponsor