Let’s go through generic methods and classes in C# β€” a powerful feature that allows you to write type-safe, reusable code.


πŸ“Œ 1. What Are Generics?

Generics allow you to define a class, method, or interface with a placeholder for the type instead of using a specific data type.

  • Improves type safety (no need for casting)

  • Reduces code duplication

  • Commonly used in collections like List<T>, Dictionary<K,V>, etc.


πŸ“Œ 2. Generic Classes

Instead of hardcoding the data type (like int or string), you leave a placeholder (called a type parameter), and when you use the class, you specify the type. The type parameter in a generic class (or method) can be named anything you like. In this case we’ll use T.

Syntax

public class GenericClass<T>
{
    private T value;
 
    public GenericClass(T value)
    {
        this.value = value;
    }
 
    public T GetValue()
    {
        return value;
    }
}

Usage

GenericClass<int> intObj = new GenericClass<int>(10);
Console.WriteLine(intObj.GetValue()); // 10
 
GenericClass<string> strObj = new GenericClass<string>("Hello");
Console.WriteLine(strObj.GetValue()); // Hello
  • T is a placeholder type

  • Can be replaced with any type when creating an object


πŸ“Œ 3. Generic Methods

  • A method can also be generic, independent of the class

  • Type is specified when calling the method

Syntax

public T Add<T>(T a, T b)
{
    dynamic x = a;
    dynamic y = b;
    return x + y;
}

Usage

var result1 = Add<int>(5, 10);      // 15
var result2 = Add<double>(2.5, 3.5); // 6.0
  • Type T is replaced at compile time

  • Generic methods can exist inside generic or non-generic classes


πŸ“Œ 4. Constraints on Generics

Sometimes you want to restrict the type that can be used. Use constraints:

ConstraintMeaning
where T : classMust be a reference type
where T : structMust be a value type
where T : new()Must have a public parameterless constructor
where T : SomeBaseMust inherit from a specific base class
where T : interfaceMust implement an interface

Example: Constraint

public class Repository<T> where T : class, new()
{
    public T Create()
    {
        return new T();
    }
}
  • Ensures T is a class with a parameterless constructor

πŸ“Œ 5. Why Use Generics?

  1. Type Safety β†’ Catch type errors at compile time

  2. Code Reusability β†’ One class or method works with many types

  3. Performance β†’ Avoids boxing/unboxing for value types

  4. Consistency β†’ Works well with collections


πŸ“Œ 6. Summary Table

FeatureDescriptionExample
Generic ClassClass with type parameter <T>GenericClass<T>
Generic MethodMethod with type parameter <T>T Add<T>(T a, T b)
ConstraintsRestrict types allowed for Twhere T : class, new()
BenefitsType safety, reusability, performanceList<T>, Dictionary<K,V>

βœ… Tip:

  • Use generic classes for reusable components like repositories, data structures

  • Use generic methods for utility functions that work with multiple types