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:
Constraint | Meaning |
---|---|
where T : class | Must be a reference type |
where T : struct | Must be a value type |
where T : new() | Must have a public parameterless constructor |
where T : SomeBase | Must inherit from a specific base class |
where T : interface | Must 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?
-
Type Safety β Catch type errors at compile time
-
Code Reusability β One class or method works with many types
-
Performance β Avoids boxing/unboxing for value types
-
Consistency β Works well with collections
π 6. Summary Table
Feature | Description | Example |
---|---|---|
Generic Class | Class with type parameter <T> | GenericClass<T> |
Generic Method | Method with type parameter <T> | T Add<T>(T a, T b) |
Constraints | Restrict types allowed for T | where T : class, new() |
Benefits | Type safety, reusability, performance | List<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