I understand that this is forbidden because there are rules against him. I am confused why this is not allowed.
General rule: a user transformation should in no way replace an inline transformation. There are subtle ways that this rule can be broken using common types, but you specifically say that you are not interested in scripts of a typical type.
You cannot, for example, do a custom conversion from MyClass to Object , because there is already an implicit conversion from MyClass to Object . An inline transform will always win, so you can declare that a custom transform will be meaningless.
In addition, you cannot even do a custom implicit conversion that replaces the built-in explicit conversion. You cannot, for example, do an implicit user conversion from Object to MyClass , because there is already a built-in explicit conversion from Object to MyClass . This is too confusing for the code reader to allow you to arbitrarily reclassify existing explicit conversions as implicit conversions.
This is especially true of personality. If I say:
object someObject = new MyClass(); MyClass myclass = (MyClass) someObject;
then I expect this to mean that " someObject really is of type MyClass , this is an explicit reference conversion, and now MyClass and someObject are reference equals." If you were allowed to say
public static implicit operator MyClass(object o) { return new MyClass(); }
then
object someObject = new MyClass(); MyClass myclass = someObject;
will be legal, and the two objects will not have reference equality, which is bizarre.
We already have enough rules to disqualify code that is converted from an interface to an unsealed class type. Consider the following:
class Foo { } class Foo2 : Foo, IBlah { } ... IBlah blah = new Foo2(); Foo foo = (Foo) blah;
This works, and it is reasonable to expect that blah and foo are reference equal, because casting Foo2 to its base type Foo does not change the link. Now suppose this is legal:
class Foo { public static implicit operator Foo(IBlah blah) { return new Foo(); } }
If this is legal, then this code is legal:
IBlah blah = new Foo2(); Foo foo = blah;
we just converted an instance of a derived class to its base class, but they are not referenced. This is weird and confusing, so we make it illegal. You simply cannot declare such an implicit conversion because it replaces the existing built-in explicit conversion.
Thus, the rule that you should not replace any inline transformation with any custom transformation is sufficient to deny the possibility of creating a transformation that accepts an interface.
But wait! Suppose foo sealed. Then there is no conversion between IBlah and foo , explicit or implicit, because the derivative Foo2 that implements IBlah cannot be obtained. In this case, should we allow custom conversion between foo and IBlah ? Such a custom conversion cannot replace any built-in conversion, explicit or implicit.
No. We have added an additional rule to section 10.10.3 of the specification, which explicitly prohibits any user transformation to or from an interface, regardless of whether or not the inline transformation replaces or does not replace.
Why? Since you have a reasonable expectation that when one converts a value to an interface, you check to see if this object implements the interface without requesting a completely different object that implements the interface. In COM terms, converting to the QueryInterface interface is "Do you implement this interface?" - and not QueryService - "can you find me for those who implement this interface?"
Similarly, there is a reasonable expectation that when one is converted from an interface, one asks if the interface is really implemented by an object of a given target type and does not require that the object of the target type be completely different from the object that implements the interface.
Thus, it is always forbidden to do a custom conversion that is converted to or from an interface.
However, generics are highly polluting waters, the wording of the specification is not very clear, and the C # compiler contains a number of errors in its implementation . Neither the specification nor the implementation is correct, given some cross-cases related to generics, and this is a difficult problem for me, the executor . I actually work with Mads today to clarify this section of the specification, as I will be implementing it at Roslyn next week. I will try to do this with as few changes as possible, but a small number may be required to bring the compiler behavior and specification language into line with each other.