What are Generics in C# ?

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. Generics facilitate type safety, improved performance and reduced code. It promotes the usage of parameterized types on our types and is also known as parametric polymorphism.
 
The Common Language Runtime (CLR) compiles any Generic type to IL and Metadata as it does with the other types; but it stores added information pertaining to the generic types which is used to bind the generic type to a specific type at runtime when the generic type is instantiated. Note that for generic types that are bound to value types, the generic types are instantiated for each value type that it is bound to.
 
Unlike this, for generic types that are bond to reference types, the generic type instance refers to the location in memory of the reference type to which it is bound for all the instances of the generic type. The following code piece in the given Example-1 shows how a generic type can be implemented.
 
Example-1
 
public class Test 
 {
     public void Display() 
       {
           //Some code
       }
 //Other members
 }
 
We may say that the type parameter is an unbound type as it is not bound to any specific type. When we instantiate this class, the generic type has to be bound to a particular type as shown in the code piece in the Example-2.
 
Example-2
 
Test test = new Test();
 
Note that in the above code piece, the resulting type called “test” is a bound type. The code Example-3 shows how we can use a generic method on varied types.
 
Example-3: Implementing a generic method
 
using System;  
using System.Collections.Generic;  
class Test  
{  
static void Main( string[] args )  
{  
Test t = new Test();
	int[] integerArray = {1,2,3,4,5,6};  
	char[] characterArray = { 'J', 'O', 'Y', 'D', 'I','P' };   
	double[] doubleArray = {0.1,0.2,0.3,0.4,0.5,0.6};  
	Console.WriteLine( "Displaying the  contents of the integer array:--" );  
	t.Display(integerArray);
	Console.WriteLine( "Displaying the contents of the character array:--" );
	t.Display(characterArray);
	Console.WriteLine( "Displaying the contents of the double array:--" );
	t.Display(doubleArray);
}
   
public void Display< GenericArray >( GenericArray[] array )  
{  
	for (int i = 0; i< array.Length; i++)  
		Console.WriteLine(array[i]);  
}
}
 
The following points sum up the basic advantages of using Generics.
 
• Efficiency of Code

• Enhancement of performance

• Type Safety and reliability

• Maintainability of code

 
Comparison between C# Generics and C++ Templates
 
According to MSDN, “Generics and templates are both language features that provide support for parameterized types. However, they are different and have different uses.” C# generics and templates in C++ are comparatively similar syntactically. However, there are some notable differences between them.
 
C# Generic types are strong typed and they are instantiated at the runtime whereas C++ Templates are loosely typed and they are instantiated at the compile time only. Further, unlike C++ templates, Generics do not permit the type parameters to have default values.
 
MSDN states, “C++ templates use a compile-time model. When a template is used in a C++ program, the effect is as if a sophisticated macro processor had been used. C# generics are not just a feature of the compiler, but also a feature of the runtime.
 
A generic type such as List maintains its generic-ness or genericity after it has been compiled. Or, to look at it another way, the substitution that the C++ compiler does at compile time is done at JIT time in the C# generic world.”
 
System.Collections.Generic Namespace
 
The System.Collections.Generic namespace contains several generic collection classes based on generics and it is recommended that we should use these collection classes in place of the earlier non-generic ones for better performance of our applications.
 
According to MSDN, “The System.Collections.Generic namespace contains interfaces and classes that define generic collections, which allow users to create strongly typed collections that provide better type safety and performance than non-generic strongly typed collections.”
 
Note that the System.Collections.Generic.ICollection interface is the base interface for all the classes in the System.Collections.Generic namespace.
 
Implement a Generic Stack Class
 
Let us understand the Generics with a simple example. Here I have implemented a stack in two different ways. A stack that can be re-collected, works in the LIFO (Last-In-First-Out) principle.
 
If we implement a stack that can accept any data type or object and store the same in to it, we have to opt for an object based stack (obviously if we are not using Generics). I have given here two code examples of a partial implementation of a stack.
 
The first one is an object based stack and the next a generic stack. The object based stack would require boxing and unboxing operations to store and return objects in and out of the stack, but the generic stack (the one that uses C# Generics) would not. Hence, as far as performance is concerned, the generic stack is the better choice.
 
The code in Example-4 is an example of an object based stack. Note that we can store any type of data in this stack, but we need to perform an explicit cast in order to retrieve the right type of the object that was stored using boxing and unboxing. This can be a significant performance overhead.
 
Example-4
 
using System;
 using System.Collections.Generic;
 using System.Text;
  
 namespace Generics
 {
     public class CustomStack
     {
         const int size = 10;
         private object[] register;
  
         private int count = 0;
  
         private CustomStack()
         {
             register = new object[size];
         }
         public void Push(object x)
         {
             if (count < size)
                 register[count++] = x;
         }
         public object Pop()
         {
             return register[--count];
         }
         static void Main(string[] args)
         {
             CustomStack intStack = new CustomStack();
             intStack.Push(10);
             int i = (int)intStack.Pop();
             Console.WriteLine(i);
             Console.Read();
         }
     }
 }
 
When using the object based stack, you have to box and unbox the elements in order to push and pop them in and out of the stack resulting in a significant performance drawback. Now, Generics comes to the rescue the process. It is much more flexible and removes the overhead involved in boxing and unboxing operations that a generic type is assigned a specific type only at runtime.
 
The type checks are done at the compile time itself. Hence, the generic stack in our example works much faster compared to its non-generic counterpart. The following is the implementation of a generic stack using C# Generics.
 
Example-5
 
using System;
 using System.Collections.Generic;
 using System.Text;
  
 namespace Generics
 {
     public class CustomStack<S>
     {
         const int size = 10;
         private S[] register;
         private int count = 0;
  
         public CustomStack()
         {
             register = new S[size];
         }
  
         public void Push(S x)
         {
             if (count < size)
                 register[count++] = x;
         }
  
         public S Pop()
         {
             return register[--count];
         }     
    }
  
     public class Test
     {
         static void Main(string[] args)
         {
             CustomStack<int> intStack = new CustomStack<int>();
             intStack.Push(10);
             int i = intStack.Pop();
             Console.WriteLine(i);
             Console.Read();
         }
     }
 }