Why use generic constraints in C#

You ask, “can’t I switch ALL references of T in this class with ISomething?” So I think you mean to compare:

public class MyClass<T> where T : ISomething 
{ 
    public T MyProperty { get; set; }
}

With:

public class MyClass 
{
    public ISomething MyProperty { get; set; }
}

In the second example, MyProperty is only guaranteed to be an instance of ISomething. In the first example, MyProperty is whatever T is, even if that is a specific subtype of ISomething. Consider a concrete implementation of ISomething:

public class MySomething : ISomething
{
    public string MyOtherProperty { get; set; }
}

Now, if we use the first, generic, example, we could have:

MyClass<MySomething> myClass = new MyClass<MySomething>();
Console.WriteLine(myClass.MyProperty.MyOtherProperty);

On the other hand, if we used the second example, we wouldn’t be able to access MyOtherProperty since it’s only known to be an ISomething:

MyClass myClass = new MyClass();
Console.WriteLine(myClass.MyProperty.MyOtherProperty); // Won't compile, no property "MyOtherProperty"

On a different note, the reason these type constraints are useful is that you can refer to MyProperty (type T) and access members of ISomething. In other words, if ISomething were declared like:

public interface ISomething 
{
    public string SomeProperty { get; set; }
}

Then you could access MyProperty.SomeProperty. If you omitted the where T : ISomething then you wouldn’t be able to access SomeProperty since T would only be known to be of type object.

Leave a Comment