Generics in C#: A Comprehensive Guide with Code Examples and Explanations

Generics in C# allow you to write type-safe, reusable, and efficient code. In this comprehensive guide, you will learn everything you need to know about generics including how to create generic classes, methods, collections, and generic constraints. This article contains valuable information about C# generics that will help both beginners and experienced C# developers enhance their coding abilities.

C# Generics allow you to reuse the same code (class or method) with different data types. It refers to a generalized version of something rather than a specialized version.

Generics in C#
Generics in C#

What are Generics in C#?

C# generics enable the creation of a class or method that can handle multiple data types without having to create separate codes for each type. This results in type-safe and reusable code as the compiler ensures that the correct data type is used.

Generics was first introduced in C# version 2.0 and they offer the ability to make our code more flexible by not tying it to a specific data type. This allows us to reuse classes or methods with different data types which makes our code more versatile.

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

Creating a Generic Class in C#

We can use the angle bracket syntax followed by the type parameter to create a generic class in C#. Here is an example of a generic class that can be used to store values of any data type:

public class GenericClass<T>
{
    private T value;

    public T Value
    {
        get { return value; }
        set { this.value = value; }
    }
}

To use this class, you simply need to specify the data type you want to use when creating an instance of the class. For example:

GenericClass<int> intInstance = new GenericClass<int>();
intInstance.Value = 100;

GenericClass<string> stringInstance = new GenericClass<string>();
stringInstance.Value = "Hello, World!";

C# Generic Class Characteristics

Generics in C# offer several key benefits and characteristics that make them an essential part of development.
Generics have important features, like:

  • Reusability: One of the most significant benefits of generic classes is that they enable you to write code that can be utilized for various data types. This decreases the amount of code required to be written and aids in preventing the duplication of codes.
  • Type-Safety: Generics ensure that only the correct data type is used when creating a class. This eliminates the need for type-casting and reduces the risk of runtime errors.
  • Improved Performance: Generics can improve the performance of your code by avoiding the overhead of boxing and unboxing data types.
  • Better Code Readability: Generics make your code easier to understand by clearly showing the data types used. This helps other developers understand your code and reduces the chance of mistakes or bugs.

Here is an example to demonstrate some of the characteristics of generic classes:

public class GenericClass<T>
{
    private T data;

    public T Data
    {
        get { return this.data; }
        set { this.data = value; }
    }
}

// Use the generic class with different data types
GenericClass<int> intClass = new GenericClass<int>();
intClass.Data = 100;

GenericClass<string> stringClass = new GenericClass<string>();
stringClass.Data = "Hello World!";

// Type-safety is enforced at compile-time
GenericClass<int> intClass = new GenericClass<int>();
intClass.Data = "This is a string"; // Compile-time error

Why do we use generics in C#?

Generics in C# help developers in several ways. It allows code to be reused, safe, and faster. A developer can write code that works with different types of data when using generics. This makes the code more efficient and easier to read and maintain. Generics ensure that only appropriate data types are stored or used in methods for extra safety and to avoid boxing and unboxing.

C# Generic class example

A generic class can be created by specifying an actual type in <> angle brackets. The following is an example to create a generic class in C#.

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();
        }
    }
}

Output:

Generics in C# class output

Generic Methods

Generic methods are created to be used with different data types. A generic method allows you to write reusable and type-safe code. It is defined with a type parameter using an angle <> brackets.
Here is an example of a simple generic method in C#:

public class GenericMethodExample
{
    public static void Swap<T>(ref T x, ref T y)
    {
        T temp = x;
        x = y;
        y = temp;
    }
}

In this example, the Swap method takes two arguments of type T and swaps their values. The T type parameter can be any data type, including value types, reference types, and even other generic types.

Let’s pass two values you want to swap in this generic method:

int x = 5;
int y = 10;

GenericMethodExample.Swap<int>(ref x, ref y);

Console.WriteLine("x = {0}, y = {1}", x, y); // Output: x = 10, y = 5

You can also use generic methods with other generic types, like this:

List<int> list1 = new List<int> { 10, 20, 30 };
List<int> list2 = new List<int> { 40, 50, 60 };

GenericMethodExample.Swap<List<int>>(ref list1, ref list2);

foreach (int item in list1)
{
    Console.WriteLine(item);
}

// Output: 40, 50, 60

In this example, the Swap method is used to swap two List<int> objects.

Generic method in C#
Generic methods in C# example.

Example 2:

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

If you observe the above code, we call our generic method (MyGenericMethod) with different types of arguments based on our requirements.

C# Generic field

A generic field in C# is a field that is defined to hold values of a specific type, which can be specified when the class or struct is instantiated. The type can be any valid data type, including reference types and value types.

Here is an example of a generic field in C#:

using System;
namespace GenericsExample
{
    //Here T specifies the Data Type of class and field
    class MyGenericClass<T>
    {
        //Generic field/Variable    
        public T GenericField;      
    }
    class Program
    {
        static void Main()
        {
            MyGenericClass<string> myGenericClass = new MyGenericClass<string>();
           string value =  myGenericClass.GenericField = "Generic Field";

            Console.WriteLine(value);
            Console.ReadKey();
        }
    }
    // Output: Generic Field
}

Generic Type Constraints

You can use generic constraints to limit the types of data that can be used with a generic class or method. There are different types of constraints in C#.

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

  • where T: struct – This constraint requires that the data type be a value type.
  • where T: class – This constraint requires that the data type be a reference type.
  • where T: new() – This constraint requires that the data type have a default constructor.
  • where T:<base class name> – This constraint requires that the data type inherit from the specified base class.
  • where T:<interface name> – This constraint requires that the data type implement the specified interface.
Generic type constraints
C# Generic Constraints

Here is an example of a generic class that uses a generic constraint to require that the data type implement the IComparable interface:

public class GenericClassWithConstraints<T> where T : IComparable
{
    private T value;

    public T Value
    {
        get { return value; }
        set { this.value = value; }
    }

    public int CompareTo(T other)
    {
        return value.CompareTo(other);
    }
}

Advantages of Generics in C#

Generics in C# provide several key advantages over non-generic code. Some of the most important benefits of using generics in C# are listed below:

AdvantageExplanation
Reusability:Generics allow you to write reusable code that can be used with different data types. This saves time and effort as you don’t need to write separate code for each data type you want to work with.
Type Safety:Generics enforce type safety at compile-time which prevents type mismatch errors that can occur at runtime. This makes your code more reliable and easier to maintain.
Performance:Generics can improve performance by allowing the compiler to generate optimized code for the data type being used. This can result in faster execution times and reduced memory usage.
Better readability:Generics make your code more readable by making the type of data being used explicitly. This can help you and other developers understand the code better and avoid errors.

Some of the existing generic classes and interfaces available in C# are listed below:

To know more about the collection please refer to this link:  Collections in C#: Queue, Stack, ArrayList, and Hashtable

Also, refer to this link to read about Generic Delegate in C#.

References MSDN: Generic Classes and Methods

FAQs

Q: What are generics in C#?

Generics in C# allow you to write code that can work with multiple data types. They allow you to create reusable code that can be used with different types of data while maintaining type safety and performance.

Q: How can you create a generic class in C#?

You can create a generic class by putting the specific type inside angle <> brackets when creating an instance. For example, in the code “MyClass obj = new MyClass();”, we are creating an instance of the generic class “MyClass” and using “string” as the specific type.

Q: Can you use generics with multiple data types?

Yes, you can use generics with multiple data types by specifying constraints on the placeholder data type. This allows you to specify which data types the generic class or method can be used with.

Q: What are the benefits of using generics in C#?

Some of the key benefits of using generics in C# are increased code reusability, improved type safety, better performance, and enhanced code readability.

Recommended Articles:

Please share this post and let us know what you think in the comments.

Shekh Ali
4.5 2 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments