The compiler cannot throw an error on the line
IGeneric<Base> b = x; Console.WriteLine(b.GetName());
because there is no ambiguity that the compiler can know about. GetName() actually a valid method on the IGeneric<Base> interface. The compiler does not track runtime b to know that there is a type that can cause ambiguity. Therefore, he stayed until runtime to decide what to do. Runtime may throw an exception, but the CLR developers apparently decided against this (which I personally consider a good solution).
In other words, let's say that instead you just wrote a method:
public void CallIt(IGeneric<Base> b) { string name = b.GetName(); }
and you do not provide classes that implement IGeneric<T> in your assembly. You distribute this, and many others implement this interface only once and can simply call your method. However, someone eventually consumes your assembly and creates a DoubleDown class and passes it to your method. At what point should the compiler give an error? Of course, an already compiled and distributed assembly containing a call to GetName() cannot lead to a compiler error. It can be said that assignment from DoubleDown to IGeneric<Base> is ambiguous. but again, we could add another level of indirection to the original assembly:
public void CallItOnDerived1(IGeneric<Derived1> b) { return CallIt(b);
And again, many consumers can call either CallIt or CallItOnDerived1 and be fine. But our consumer DoubleDown transition also makes a completely legal call that could not cause a compiler error when calling CallItOnDerived1 , since the conversion from DoubleDown to IGeneric<Derived1> should, of course, be in order. Thus, there is no point at which the compiler may DoubleDown error other than the DoubleDown definition, but that would preclude the possibility of doing something potentially useful without a workaround.
I really answered this question in more detail elsewhere, and also provided a potential solution if the language could be changed:
There are no warnings or errors (or runtime failures) when contravariance leads to ambiguity
Given that the likelihood of a language change to support this is almost null, I think the current behavior is fine, except that it should be outlined in the specifications so that all CLR implementations can be expected to behave the same way.
jam40jeff Feb 09 '13 at 7:32 2013-02-09 07:32
source share