Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the point of having constraints for type parameters in .NET (base class and interface constraints)

Tags:

c#

.net

generics

I'm working on a small class library at work, and it naturally involves using generics for this task. But there is this thing that I don't really understand with generics: Why would I need to use generic type parameters, and then constrain the the type parameter to a specific base class or interface.

Here's an example to what I mean:

public class MyGenericClass<T> where T : SomeBaseClass
{
    private T data;
}

And here's the implementation without generics

public class MyClass
{
    private SomeBaseClass data;
}

Are these two definitions the same (if yes, then i don't see the advatage of using generics here)?

If not, what do we benefit from using generics here?

like image 276
Avi Shilon Avatar asked Apr 30 '12 13:04

Avi Shilon


4 Answers

As with almost all uses of generics, the benefit comes to the consumer. Constraining the type gives you the same advantages that you get by strongly typing your parameter (or you can do other things like ensure that there's a public parameterless constructor or ensure that it's either a value or reference type) while still retaining the niceties of generics for the consumer of your class or function.

Using generics also, for example, allows you to obtain the actual type that was specified, if that's of any particular value.

This example is a little contrived, but look at this:

public class BaseClass
{
    public void FunctionYouNeed();
}

public class Derived : BaseClass
{
    public void OtherFunction();
}

public class MyGenericClass<T> where T: BaseClass
{
    public MyGenericClass(T wrappedValue)
    {
        WrappedValue = wrappedValue;
    }

    public T WrappedValue { get; set; }

    public void Foo()
    {
        WrappedValue.FunctionYouNeed();
    }
}

...

var MyGenericClass bar = new MyGenericClass<Derived>(new Derived());

bar.Foo();

bar.WrappedValue.OtherFunction();
like image 77
Adam Robinson Avatar answered Oct 01 '22 22:10

Adam Robinson


The difference is that the former defines the new class as a specific type; the latter simply defines a plain class with a field of that type.

like image 40
David W Avatar answered Oct 01 '22 23:10

David W


It's all about type safety. Using generics you can return a concrete type (T) instead of some base type which defines the API you need in your generic class. Therefore, the caller of your method won't have to cast the result to the concrete type (which is an error-prone operation).

like image 33
Marek Dzikiewicz Avatar answered Oct 01 '22 22:10

Marek Dzikiewicz


The main difference is in usage. In the first case, the usage can have:

MyGenericClass<SomeDerivedClass> Variable
Variable.data.SomeDerivedProperty = X

And so that when you use that class, you can still access anything from SomeDerivedClass without casting back to it.

The second example will not allow this.

MyClass.data = SomeDerivedClassInstance
MyClass.data.SomeDerivedProperty = X //Compile Error
((SomeDerivedClass)MyClass.data).SomeDerivedProperty = X //Ewwwww

You will have to cast back up to the SomeDerivedClass (which is unsafe) to use something specific to the derived class.

like image 37
Rangoric Avatar answered Oct 01 '22 23:10

Rangoric