If I have a generic interface with a covariant type parameter, like this:
interface IGeneric
{
string GetName();
}
And If
The question asked, "Why doesn't this produce a compiler warning?". In VB, it does(I implemented it).
The type system doesn't carry enough information to provide a warning at time of invocation about variance ambiguity. So the warning has to be emitted earlier ...
In VB, if you declare a class C
which implements both IEnumerable(Of Fish)
and IEnumerable(Of Dog)
, then it gives a warning saying that the two will conflict in the common case IEnumerable(Of Animal)
. This is enough to stamp out variance-ambiguity from code that's written entirely in VB.
However, it doesn't help if the problem class was declared in C#. Also note that it's completely reasonable to declare such a class if no one invokes a problematic member on it.
In VB, if you perform a cast from such a class C
into IEnumerable(Of Animal)
, then it gives a warning on the cast. This is enough to stamp out variance-ambiguity even if you imported the problem class from metadata.
However, it's a poor warning location because it's not actionable: you can't go and change the cast. The only actionable warning to people would be to go back and change the class definition. Also note that it's completely reasonable to perform such a cast if no one invokes a problematic member on it.
Question:
How come VB emits these warnings but C# doesn't?
Answer:
When I put them into VB, I was enthusiastic about formal computer science, and had only been writing compilers for a couple of years, and I had the time and enthusiasm to code them up.
Eric Lippert was doing them in C#. He had the wisdom and maturity to see that coding up such warnings in the compiler would take a lot of time that could be better spent elsewhere, and was sufficiently complex that it carried high risk. Indeed the VB compilers had bugs in these very warnings that were only fixed in VS2012.
Also, to be frank, it was impossible to come up with a warning message useful enough that people would understand it. Incidentally,
Question:
How does the CLR resolve the ambiguity when chosing which one to invoke?
Answer:
It bases it on the lexical ordering of inheritance statements in the original source code, i.e. the lexical order in which you declared that C
implements IEnumerable(Of Fish)
and IEnumerable(Of Dog)
.