(Following the comments of the accepted answer.)
Yes, this is a very, very confusing part of the specification. The whole bit about the "spanning types" in particular is deeply corrupt. Iβve been trying for several years to find the time to completely rewrite this entire section into something more consistent, but there has never been a high enough priority.
In fact, we have a contradiction; we say that there are no user implicit conversions involving interfaces, but it is clear that this is not true in this case; there is a custom implicit conversion from IC to Foo<IC> , demonstrated by the fact that the string goes to Foo<IC> through this conversion.
What we really need to emphasize better is the line you quoted:
In particular, it is not possible to override an existing implicit or explicit conversion.
What motivates it all; the desire to not let you ever think that you are executing a type test that preserves the view when you are actually calling the user 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 this cause an explicit user-defined transformation or not? The object is indeed derived from Foo, so you hope this does not happen; it should be a simple type test and reference job, not a call to a helper method. Casting the value of an interface is always considered a type test, since it is almost always possible that an object really has this type and really implements this interface. We do not want to deny you the opportunity to make a cheap transformation that preserves the view.
Eric Lippert Jul 30 '09 at 21:40 2009-07-30 21:40
source share