Generics in .Net

Introduction

Generics (in the "System.Colloections.Generic" namespace) were introduced in a previous version of .Net (actually the Common Language Infrastructure (CLI)). It's not a new concept; it's available in C++ in the form of templates.

It is an important feature of .Net programming, allowing a class and methods such as lists, hash table, and queue and so on to be defined with a type T as a parameter.

The type of generic parameter is specified only at the time of declaration. With the help of this, the programmer will improve performance of an application and type-safety.

A Generic class encapsulates operations that do not have a specific data type.

Generics are also known as Parametric polymorphism.

Example

You can write a single class MyList<T> and you can use the code as MyList<int>,  MyList < string > or MyList<MyClass>. Without any casting or boxing operation.
 
Advantages of using generic

A ArrayList is a highly convenient collection class that can be used without modification to store any reference or value type. 

Generics provide a solution for the limitation of an Arraylist collection in the Common Language Runtime.

We will see the limitations of non-generic collection classes, using the ArrayList collection class.

using System;

using System.Collections;

 

public class ArrayList

{

    static void ArrayList()

    {

 

        // Creates and initializes a new ArrayList.

        ArrayList List1 = new ArrayList();

        List1.Add("Hello");

        List1.Add("World");

 

        // Creates and initializes a new ArrayList.

        ArrayList List2 = new ArrayList();

        List2.Add(1);

        List2.Add(2);

    }

}

In the ArrayList Collection, any reference or value type data added to an ArrayList must be typecast to "System.Object". If the items are value types then they must be boxed when they are added to the list, and unboxed when they are retrieved. The casting, boxing, unboxing operation reduce the performance.

In a generic List<T> collection, using the "System.Collections.Generic" namespace,

we will see the same operation.
 

using System;

using System.Collections.Generic;

public class TArrayList

{

    public static void ArrayList()

    {

        List<int> List1 = new List<int>();

        // No boxing, no casting:

        List1.Add(3);

    }

}

  
As compared to Arraylist it would be safer and faster.

  • Code Reusability in generics  (Advantage)

Generics provide type-safe code with re-usability.  
 
Example

Suppose you need to sort the integer and floating type numbers, let's see how to do it in collections and generics.
 
The following shows how to do it in a collection:

using System.Collections;

 

public class GenerciArrayList

{

    public static void Sort()

    {

        int[] intArray = { 8, 10, 2, 6, 3 };

 

        // Sort your int array

        Array.Sort(intArray);

        foreach (var i in intArray)

        {

            Console.WriteLine(i);

        }

        // Sort it the other way

 

        string[] strArray = { "A", "D", "C", "E", "B" };

        Array.Sort(strArray);

 

        foreach (var i in strArray)

        {

            Console.WriteLine(i);

        }

        Console.ReadLine();

    }

}

The following shows how to do it using Generics:
 

using System.Collections.Generic;
 

public class ArrayList

{

    private static object[] Sort<T1>(object[] iInputeArray)

    {

        Array.Sort(iInputeArray);

        return iInputeArray;

    }

}
 
Here T is a type. Once we can create this method, we can call it with various data types as follows.
 
In this way a Generic provides code re-usability.
    

 public  static void SortList()

 {

      object[] iInputArray = { 3, 5, 8, 6, 10, 6, 2, 1, 12 };

      iInputArray = Sort<int>(iInputArray);

 

     foreach (Object obj in iInputArray)

     Console.Write("   {0}", obj);

 

    object[]strInputArray = { "A" ,"C", "T", "R", "E", "D"  };

    strInputArray = Sort<int>(strInputArray);

 

    foreach (Object obj in strInputArray)

    Console.Write("   {0}", obj);

 

    Console.WriteLine();

    Console.ReadLine();

 }


Benefits

The following are the benefits of generics:

  • There is no need of casting for accessing the elements of data.
  • Code is not duplicated for multiple types of data.
  • Generic can hold the data with same type and we can decide what type of data that collection hold.
  • You can create your own generic interface, classes, method, events and delegate.

Why use Generics?

There are mainly two reasons to use generics as in the following:

  1. Performance: Collections that store the objects uses boxing and unboxing on data types. A collection can reduce the performance.
    By using generics it helps to improve the performance and type safety.
  2. Type Safety: there is no strong type information at compile time as to what it is stored in the collection.

When to use Generics

  • When you use various undefined data types, you need to create a generic type.
  • It is easier to write code once and reuse it for multiple types.
  •  If you are working on a value type then for that boxing and unboxing operation will occur, Generics will eliminate the boxing and unboxing operations.

Boxing: Conversion of a value type into a reference type of variable. When the variable of a value type is to be converted to a reference type, the object box is allocated to hold the value, and copies the value into a box.

Unboxing: It is just the opposite of boxing.   
                                                              
Example Boxing/Unboxing

Class BoxUnbox

{

  Static void Main ()

  {

     Int i=1;

     Object o=i;    //boxing

     Int j = (int) o; //unboxing

  }

}          


Generic Class

The common use of a generic class is with collections like a linked list, hash table, stack, queue, and tree. The addition and removal of an item from a collection is basically the same.

Example  
 

using System.Collections.Generic;

namespace Generic

{

    public class ArrayClass<T>

    {

        object Store;

        public void Push(object Obj)

        {

            Store = Obj;

        }

        public object Pop()

        {

            return Store;

        }

    }

}


Here T is a type of parameter.  We can pass any data type as a parameter.

This class can be used as below.
 

public class SubClass

{

    public static void MyClass()

    {

        ArrayClass<int> intArray = new ArrayClass<int>();

        intArray.Push(10);

        object intReturnValue = intArray.Pop();

        Console.Write("   {0}", intReturnValue);

 

        ArrayClass<string> strArray = new ArrayClass<string>();

        strArray.Push("Hello word");

        object strReturnValue = strArray.Pop();

        Console.Write("   {0}", strReturnValue);

        Console.ReadLine();

    }

}
 
Generic Methods

Generic methods are the method yet declared with type parameters.

Examples
 

using System.Collections.Generic;

 

public class ArrayList

{

    static void Swap<T>(ref T lhs, ref T rhs)

    {

        T temp;

        temp = lhs;

        lhs = rhs;

        rhs = temp;

    }

}
 
The following method shows how to call the method above.
 

public static void TestSwap()

{

    int a = 1;

    int b = 2;

    Swap<int>(ref a, ref b);

    System.Console.WriteLine(a + " " + b);

    Console.ReadLine();

}


Conclusion

 We used a generic type provided by the .Net Framework. These include the dictionary and list. But you can provide your own type.