Generics in C# .NET With Examples

In this article, we are going to talk about the use of Generics in C# with multiple examples.

Generics in C#
Generics in C#

Generic refers to a generalized version of something rather than a specialized version. Generics allows you to define types (classes and interfaces) and methods using the type parameters without specifying a specific data type. It allows you to reuse the same code with different data types.
When constructing an instance of the generic type, a type argument serves as a placeholder for a specific type.

C# Generics

Generics were first introduced in the C#.NET Framework 2.0. Generics make our code type-independent, allowing us to reuse it with different data types.

For example, List in C# is a generic collection that can be used with the different data types, such as List<int>, List<float>, List<string>, or List<Employee>

Generic in C# can be defined by using   <T> Type parameter   to decoupled the Interface, class, method, field, property, event, operator and delegate from specific data type.

Generics in C# belongs to  System.Collections.Generic  namespace which contains several generic-based collection classes.

A generic type in C# is declared after the type name in an <> angle brackets, for example. Type_Name<T> where T is a type parameter that indicates any type (value or reference) can be accepted.

<T> is just a placeholder or like a blueprint for the data type. It is substituted by the actual type by the compiler at the runtime.

Note: The Generic type parameter name can be anything as per your requirements such as  T  , TKey ,  TValue  or etc.

    • Why do we use generics?

      • C# Generics provide reusability of code as code doesn’t need to duplicate for the different data types.
      • Generics are most commonly used in C# to generate collection classes.
      • We can put constraints on generic classes so that only the selected types can be used by the client.
      • Generic types can be use to maximize code reuse, type safety, and performance.
      • Generics in C# provides a type safe approach to create collections for both reference and value types without fear of breaking its generality.
      • Unlike Object, You will get compile time errors if you try to use a different data type than the one specified in the definition.
      • Apart from type safety generics also avoid boxing and unboxing to enhance the performance.
      • In Generics there is no need for casting for accessing the elements from the collection
      • Generics allow you to add parameters to your types much like you would add parameters to your methods to extend their generality.

Declaring Generic Class In C#

In the below generic class, we have not defined the actual type of parameter during declaration. On the client-side, we can declare a specific type only when constructing an instance of the generic type.

A generic class can be created by specifying an actual type in <> angle brackets. The following is the example to create an instance of the generic class “MyGenericClass”.

using System;
namespace Generic
{
    // Generic Class
    class MyGenericClass<T>
    {
        public MyGenericClass(T parameter)
        {
            Console.WriteLine(parameter);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
          MyGenericClass<string> genericClassString = new MyGenericClass<string>("Hello");
          MyGenericClass<int> genericClassInt = new MyGenericClass<int>(100);
          MyGenericClass<float> genericClassFloat = new MyGenericClass<float>(100.5f);
          MyGenericClass<Char> genericClassChar = new MyGenericClass<Char>('A');
            Console.ReadLine();
        }
    }
}

Generics in C# class output
The output of the above program.

Generic Method in C# Example

A generic method is a method that is defined with a type parameter using angle <> brackets.
Any type of parameter can be passed to the generic methods as shown below.

Generic method in C#
Generic methods in C# example.
using System;
namespace Generic
{ 
    class MyClass
    {
        //Generic Method
        public T MyGenericMethod<T>(T parameter)
        {
            return parameter;
        }
        
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass1 = new MyClass();

            string str = myClass1.MyGenericMethod<string>("Hello");  
            
            int number = myClass1.MyGenericMethod<int>(100);

            Console.WriteLine(str);
            Console.WriteLine(number);
            Console.ReadLine();
        }
    }
}

//Output:
//Hello
//100

Generic Type Constraints – where clause in C#

Generic type constraints
C# Generic Constraints

In generic the where clause restricts the types that are used as arguments for the type parameter during instantiation of the generic type.
You will get a compile-time error if the client code uses a type that doesn’t satisfy a constraint.

In C#, Generic constraints are applied by using the  where  keyword.

The following table contains the lists of various types of constraints in C#.

C# Generic ConstraintsDefinition
where T: classThe type argument must be a reference type. This constraint can be applied to any class (non-nullable), interface, delegate, or array type in C#.
where T: class?The type argument must be a nullable or non-nullable reference type like class, interface, delegate, or array type.
where T: new()The type argument must be a reference type that has a public parameterless (default) constructor. It cannot be combined with struct and unmanaged constraints.
When used together with other constraints like class, the new() constraint must be specified last (example: where T: class, new()).
where T: structThe type argument must be non-nullable value types such as primitive data types int, double, char, bool, float, etc.
The struct constraint can’t be combined with the unmanaged constraint.
where T : <interface name>The type argument must be or implement the specified interface. Also, multiple interface constraints can be specified.
where T: UThe type argument supplied for must be or derive from the argument supplied for U. In a nullable context, if U is a non-nullable reference type, T must be a non-nullable reference type. If U is a nullable reference type, T may be either nullable or non-nullable.
C# Generic Constraints

The generic types are exists in System.Collections.Generic namespace. Some of the existing generic classes and interfaces are listed below:

Please read my previous article where I have discussed the Generic Delegate in C#.

I hope you enjoyed this post and found it useful. In case you have any doubt, please post your feedback, question, or comments.

References MSDN: Generic Classes and Methods

Leave a Comment