Search code examples
c#genericsinterfacegeneric-constraints

Cannot pass variable of type conforming to generic constraint


public interface ILovable<T> where T : IEquatable<T>
{
    T Care(T t);
}

public class Me : ILovable<int>
{
    public int Care(int i)
    {
        return i;
    }
}

Say I have the above. Now below function fails:

private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
{
    var z = me.Care(1); //cannot convert from 'int' to 'T'
}

What's failing the above piece of code? ILovable<T> has a Care function which intakes a T which is IEquatable<T>. In the above function I'm calling the same Care function and passing T which is int type. int is after all IEquatable<int>.

What am I doing wrong? Is there any work around to get it fixed?


Solution

  • The short answer is overriding variable of type T inside a generic method (or class) with a more derived type is not possible since compiler doesn't explicitly know T is that more derived type (in our case T is int), because T can be any other more derived type at run time.

    Long answer: me variable is of type ILovable<T>. Now me.Care function is expecting parameter of type that is specified on ILovable<T> which is T. Outside the Care function T can be anything that is IEquatable<T>, so int is ok. But inside the function, T has to be just T and not another derived type of IEquatable<T>. Otherwise there will be runtime error for scenarios like this:

    private static void Colour<T>(ILovable<T> me) where T : IEquatable<T>
    {
        var z = me.Care(1); 
    }
    
    ...
    
    Colour("");
    

    Right now, T is string when calling Colour(""). So me is ILovable<string>. So me.Care function expects a string as parameter but provided is an int and that is disaster.