Lesson 12 of 40
Core C#
Intermediate
โฑ 35 min
Generics โ Types, Methods & Constraints
Write reusable, type-safe code with generic classes, methods, constraints, variance, and common generic patterns.
Part 1: Generic Classes
public class Stack<T>
{
private readonly List<T> _items = new();
public void Push(T item) => _items.Add(item);
public T Pop() { var t = _items[^1]; _items.RemoveAt(_items.Count-1); return t; }
public int Count => _items.Count;
}
{
private readonly List<T> _items = new();
public void Push(T item) => _items.Add(item);
public T Pop() { var t = _items[^1]; _items.RemoveAt(_items.Count-1); return t; }
public int Count => _items.Count;
}
Part 2: Type Constraints
// where T : class โ reference type only
// where T : struct โ value type only
// where T : new() โ has parameterless constructor
// where T : IComparable<T> โ implements interface
public static T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;
Max(3, 7); // 7
Max("apple","mango"); // "mango"
// where T : struct โ value type only
// where T : new() โ has parameterless constructor
// where T : IComparable<T> โ implements interface
public static T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;
Max(3, 7); // 7
Max("apple","mango"); // "mango"
Part 3: Covariance & Contravariance
// out T = covariant (IEnumerable<Dog> โ IEnumerable<Animal>)
IEnumerable<Dog> dogs = GetDogs();
IEnumerable<Animal> animals = dogs; // โ Works!
// in T = contravariant (IComparer<Animal> โ IComparer<Dog>)
IComparer<Animal> animalCmp = GetComparer();
IComparer<Dog> dogCmp = animalCmp; // โ Works!
IEnumerable<Dog> dogs = GetDogs();
IEnumerable<Animal> animals = dogs; // โ Works!
// in T = contravariant (IComparer<Animal> โ IComparer<Dog>)
IComparer<Animal> animalCmp = GetComparer();
IComparer<Dog> dogCmp = animalCmp; // โ Works!
Part 4: Generic Repository Pattern
public interface IRepository<T> where T : class
{
Task<T?> GetByIdAsync(int id);
Task<List<T>> GetAllAsync();
Task<T> AddAsync(T entity);
Task DeleteAsync(int id);
}
{
Task<T?> GetByIdAsync(int id);
Task<List<T>> GetAllAsync();
Task<T> AddAsync(T entity);
Task DeleteAsync(int id);
}
C# in Visual Studio 2026
๐ This lesson is part of the book C# in Visual Studio 2026 by Dr. Liew Voon Kiong.
View on Amazon Kindle Edition