Generics

2 min read
On trails:CSCOREstep 6/11

Generics let you define type-safe classes, interfaces, methods and delegatesDelegatesA type-safe function pointer, so a method can be passed around like any other value.Opens in a new tab with type parameters, like <T>, that stand in for the actual data types. The specific types are determined at compile time or runtime. You get flexibility without giving up type safety.

In code

Swap<T> on line 4 has one type parameter, T. It is the type of both arguments and of the temporary variable. The commented usage at the bottom fills T in: with int on line 13, and with string on line 15.

C#
public class Utility{    // Generic method with a type parameter T    public static void Swap<T>(ref T a, ref T b)    {        T temp = a;        a = b;        b = temp;    }}// Usage:// int x = 5, y = 10;// Utility.Swap<int>(ref x, ref y); // T is int// string s1 = "hello", s2 = "world";// Utility.Swap<string>(ref s1, ref s2); // T is string

Constraints

Constraints narrow what a type parameter is allowed to be. The Microsoft Learn example in the sources defines a generic method, Factory<TInput, TOutput>(...), with three constraints on TOutput:

C#
Factory<TInput, TOutput>(...)    where TOutput : class, ICollection<TInput>, new()
  • class: TOutput is a reference type.
  • ICollection<TInput>: TOutput can be used as an ICollection<TInput>.
  • new(): TOutput has a parameterless constructor.

Constraints let the generic code make assumptions about the type parameter. With these three, the code can create a TOutput and treat it as a collection of TInput.

Where it matters

Generics are fundamental for reusable, type-safe code. They are used all over the collection classes (List<T>, Dictionary<TKey, TValue>), in LINQ, and in flexible APIs and utility functions. They also help performance, because working with value types no longer needs boxing and unboxing, and you get compile-time type checking.

Why generics exist, and what the compiler does with them at compile time and at runtime, is in its own noteGenerics at compile time and at runtimeGeneric code is type-checked by the compiler, and the types stay real at runtime.Opens in a new tab.


Sources