C#  

How to Use Generics in C# to Write Reusable and Type-Safe Code

Introduction

Generics in C# are a powerful feature that allows developers to write flexible, reusable, and type-safe code. Instead of creating separate classes or methods for different data types, generics enable you to define a single implementation that works with multiple types while maintaining compile-time type safety.

This article explains how to use generics in C#, why they are important, and how they improve code reusability and performance with real-world examples.

What Are Generics in C#?

Generics allow you to define classes, methods, interfaces, and delegates with a placeholder type (usually represented by T). This type is specified when the class or method is used.

Basic Example

class GenericClass<T>
{
    public T Data;

    public void ShowData(T value)
    {
        Console.WriteLine(value);
    }
}

class Program
{
    static void Main()
    {
        GenericClass<int> intObj = new GenericClass<int>();
        intObj.ShowData(10);

        GenericClass<string> strObj = new GenericClass<string>();
        strObj.ShowData("Hello Generics");
    }
}

In this example, the same class works with both int and string types without duplicating code.

Why Use Generics in C#?

Generics solve common problems related to code duplication and runtime errors.

Key Benefits

  • Type Safety: Errors are caught at compile time instead of runtime

  • Code Reusability: One implementation works for multiple data types

  • Performance: No boxing and unboxing for value types

  • Maintainability: Cleaner and more structured code

Generic Methods in C#

You can also create methods that work with different data types.

Example

class Utility
{
    public static void Print<T>(T value)
    {
        Console.WriteLine(value);
    }
}

class Program
{
    static void Main()
    {
        Utility.Print<int>(100);
        Utility.Print<string>("Reusable Method");
    }
}

This method can accept any type without needing multiple overloads.

Generic Collections in C#

C# provides built-in generic collections that are widely used in real-world applications.

Example Using List

using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<string> names = new List<string>();
        names.Add("Rahul");
        names.Add("Amit");

        foreach (var name in names)
        {
            Console.WriteLine(name);
        }
    }
}

Generic collections like List, Dictionary<TKey, TValue>, and Queue provide type safety and better performance.

Generic Constraints in C#

Sometimes you want to restrict the type that can be used with generics. This is done using constraints.

Example

class Calculator<T> where T : struct
{
    public T Value;
}

Here, T must be a value type (like int, double, etc.).

Common Constraints

  • where T : class → reference types only

  • where T : struct → value types only

  • where T : new() → must have a parameterless constructor

  • where T : BaseClass → must inherit from a specific class

Real-World Example of Generics

Consider a repository pattern in a real-world application.

class Repository<T>
{
    private List<T> items = new List<T>();

    public void Add(T item)
    {
        items.Add(item);
    }

    public List<T> GetAll()
    {
        return items;
    }
}

class Program
{
    static void Main()
    {
        Repository<string> repo = new Repository<string>();
        repo.Add("Data 1");
        repo.Add("Data 2");

        foreach (var item in repo.GetAll())
        {
            Console.WriteLine(item);
        }
    }
}

This allows the same repository to work with any entity type without rewriting code.

Difference Between Generics and Non-Generics

FeatureGenericsNon-Generics
Type SafetyCompile-timeRuntime
PerformanceBetter (no boxing)Slower (boxing/unboxing)
ReusabilityHighLow
Code ClarityClean and structuredLess clear

When to Use Generics

Use generics when:

  • You want reusable components

  • You want to avoid duplicate code

  • You need type safety

  • You are working with collections or data structures

Key Takeaways

  • Generics enable reusable and type-safe programming in C#

  • They reduce runtime errors and improve performance

  • They are widely used in collections, repositories, and frameworks

Summary

Generics in C# provide a clean and efficient way to write reusable and type-safe code by allowing developers to define flexible components that work with multiple data types. They improve performance by avoiding unnecessary type conversions, enhance code readability, and reduce duplication. By using generics in classes, methods, and collections, developers can build scalable and maintainable applications that follow modern software development best practices.