(Following up on the comments of the accepted answer.)
Yes, this is a very, very confusing part of the spec. The whole bit about "encompassing types" in particular is deeply flawed. I've been trying for several years now to find the time to completely rewrite that whole section into something more coherent but it has never been a high enough priority.
Essentially what we've got here is a contradiction; we say that there are no user-defined implicit conversions involving interfaces, but clearly that is not true in this case; there's a user-defined implicit conversion from IC to Foo<IC>
, demonstrated by the fact that a string goes to Foo<IC>
via that conversion.
What we really ought to be emphasizing better is this line that you quoted:
In particular, it is not possible to
redefine an already existing implicit
or explicit conversion.
That's what motivates this whole thing; the desire to not allow you to ever think that you're doing a representation-preserving type test when in fact you are calling a user-defined method. Consider for example this variation:
interface IBar {}
interface IFoo : IBar {}
class Foo<T> : IFoo
{
public static explicit operator Foo<T>(T input) { whatever }
}
class Blah : Foo<IBar> {}
...
IBar bar = new Blah();
Foo<IBar> foo = (Foo<IBar>)bar;
Now, does that call the user-defined explicit conversion or not? The object really is derived from Foo, so you would hope that it does not; this should be a simple type test and a reference assignment, not a call to a helper method. A cast on an interface value is always treated as a type test because it is almost always possible that the object really is of that type and really does implement that interface. We don't want to deny you the possibility of doing a cheap representation-preserving conversion.