๐ŸŽ“ A1Learner
๐Ÿ”
0 of 38 lessons completed

C# Generic Constraints

A generic constraint is a rule on a type parameter. It states what a type must offer before it can fill the parameter.

The biggest of two values

Biggest compares its two arguments with CompareTo. The constraint makes that call legal.

using System;

class Program
{
    static T Biggest<T>(T first, T second) where T : IComparable<T>
    {
        if (first.CompareTo(second) >= 0)
        {
            return first;
        }
        return second;
    }

    static void Main(string[] args)
    {
        Console.WriteLine(Biggest(3, 7));
        Console.WriteLine(Biggest("apple", "pear"));
    }
}

A class constraint

The class constraint accepts reference types only. A null check is then legal inside the method.

using System;

class Program
{
    static string Describe<T>(T value) where T : class
    {
        if (value == null)
        {
            return "nothing";
        }
        return "something";
    }

    static void Main(string[] args)
    {
        Console.WriteLine(Describe("text"));
        Console.WriteLine(Describe((string)null));
    }
}

A type that breaks the rule

Box has no CompareTo method. The compiler refuses the call and names the missing conversion.

using System;

class Box
{
    public int Size = 0;
}

class Program
{
    static T Biggest<T>(T first, T second) where T : IComparable<T>
    {
        if (first.CompareTo(second) >= 0)
        {
            return first;
        }
        return second;
    }

    static void Main(string[] args)
    {
        Box a = new Box();
        Box b = new Box();
        Console.WriteLine(Biggest(a, b).Size);
    }
}

Example

using System;

class Program
{
    static T Smallest<T>(T first, T second) where T : IComparable<T>
    {
        if (first.CompareTo(second) <= 0)
        {
            return first;
        }
        return second;
    }

    static void Main(string[] args)
    {
        Console.WriteLine(Smallest(9, 3));
        Console.WriteLine(Smallest("pear", "apple"));
    }
}

Key points

  • A constraint sits after the method signature, starting with the word where.
  • The IComparable constraint promises a CompareTo method.
  • The method body can then call CompareTo on the parameter type.
  • A type that breaks the rule fails at compile time.
  • The class constraint limits a parameter to reference types.

In this example, Smallest mirrors Biggest with the comparison flipped. The int call returns 3. The string call returns apple. The same constraint guards both calls.

Note

Constraints turn runtime surprises into compile errors.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does where T : IComparable<T> require of a type?