Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fun with generics: no implicit reference conversion error

I tested this code and got that it doesn't compiles.

interface IE<T>
{

}

class A<T> : IE<T>
{
    public static void F<TU>() where TU : IE<T>
    {

    }

    static void Foo()
    {
        F<A<int>>();
    }
}

It fails even if I add public static void F<TU>() where TU : A<int>, IE<T>.

afaik it's valid according to C# specs. If I remove contraint where TU : IE<T> but in this case it couldn't affect, because A<int> is subtype of IE<T>.

And it's also funny because resharper suggest to add IE<T> interface to Aenter image description here

why this code isn't valid?

like image 466
Alex Zhukovskiy Avatar asked Dec 14 '22 17:12

Alex Zhukovskiy


1 Answers

No, it's not valid. The constraint of

where TU : IE<T>

refers to the current T, i.e. the one for the type on which you're calling this method.

Consider a call of:

A<string>.Foo();

That's trying to pass A<int> as a type argument for TU, but the constraint means that there must be a reference conversion from TU to IE<string>, because T is string.

There's no conversion from A<int> to IE<string>, hence it's broken. Basically your expectation of "A<int> is subtype of IE<T>" isn't true for all T.

Now you could change it to:

public static void F<TU, TT>() where TU : IE<TT>
{
}

static void Foo()
{
    F<A<int>, int>();
}

That's now valid, because it doesn't involve T at all.

like image 60
Jon Skeet Avatar answered Dec 29 '22 11:12

Jon Skeet