Search⌘ K
AI Features

Constraining the Type Parameters

Explore how to constrain generic type parameters in C# to enforce type safety. Understand the use of constraints such as base class inheritance, reference or value types, and constructor requirements to create robust generic classes and methods.

A generic can accept any type parameter we provide. Sometimes, however, we must restrict which types are allowed to ensure our code functions correctly.

Consider a set of classes that includes an abstract Vehicle base class, Car and Truck subclasses, and a Garage class. Since we have two distinct vehicle types, it initially appears that we need two specific garage types.

Instead of creating separate classes, we create one generic Garage class:

public class Garage<T>
{
public T[] Vehicles { get; private set; }
public Garage(int garageSize)
{
Vehicles = new T[garageSize];
}
}
A generic Garage class without constraints
  • Lines 1–9: We define a generic class Garage that accepts a type parameter T.

  • Line 3: We declare an array to store items of type T.

  • Line 7: We initialize the array with the specified size.

The implementation is incomplete. As it stands, the compiler allows us to use invalid types:

// A garage that stores integers instead of vehicles???
var myStrangeGarage = new Garage<int>(20);
Instantiating the generic class with an illogical type

We create a Garage of type int. This is technically valid code because there are no constraints, but it is semantically incorrect.

The class currently accepts any type argument. We must restrict it to classes inheriting from Vehicle to ensure type safety.

We can enforce this requirement using constraints:

public class Garage<T> where T : Vehicle
{
}
Applying a base class constraint

We restrict T to be the Vehicle class or a class that derives from it using the where T : Vehicle clause. Providing a class that ...