Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constraints for overridden generic methods

Tags:

c#

generics

I am trying to understand how constraints (on class or generic methods) can affect the methods themselves. Take this code for example:

class Base<T> where T:class, IComparable<T>
{
    public virtual void Method(T obj) { }
}

class Derived<T> : Base<T> where T:class, IComparable<T>, IEnumerable<T>
{
    public override void Method(T obj) { }
}

This code compiles fine and the compiler/runtime is able to resolve polymorphic calls to the non-generic method 'Method' which takes a parameter that is of generic type. In the base class and the derived class, the constraints on the type parameter are different.

I have also specified a class constraint to keep out value types which may probably cause a problem because a different class is generated for each value-type instantiation while only one such class is instantiated for reference types.

On the other hand, the following code does not compile.

class Base
{
    public virtual void Method<T>() where T : class, IComparable<T> { }
}

class Derived : Base
{
    public override void Method<T>() where T : class, IComparable<T>, IEnumerable<T> { }
}

The language specification for C# says that the constraints on a generic method are carried over as it is to an overriding method and that it is illegal to specify any constraints as such. I did some searching for it on Google and found out that this is disallowed because of the complexities associated with supporting polymorphic calls (with respect to maintaining a method table and so on). But I still don't understand why it works in Case 1 above which is similar to this except that it is the class which is generic. How is the compiler/runtime able to do it in Case 1 while Case 2 is flagged as a compiler error?

like image 492
MS Srikkanth Avatar asked Mar 12 '23 15:03

MS Srikkanth


1 Answers

In case 1, the method can be used for any object of type T, when T is determined by the class. For any particular class, there is only one type T, so overriding is simple. The fact that you can use a wider set of types T to generate Base<T> than to generate Derived<T> is no problem.

In case 2, the methods can be called for any number of types. However, the types that are allowed in the Derived class are only a subset of the types allowed in Base class, which means you have a "partial override", which makes things a mess.

like image 94
M Kloster Avatar answered Mar 20 '23 03:03

M Kloster