Why does my translation operator from T to SomeStruct <T> work when T is an interface?

When I try to use a user-defined operator statement from an interface type to a generic structure type, I get a compilation error indicating that the type cannot be converted:

public interface J { } public struct S<T> { public static explicit operator S<T>(T value) { return new S<T>(); } } public static class C { public static S<J> Test(J j) { return (S<J>)j; // <- error: cannot convert type 'J' to type 'S<J>' } } 

Note that if J was a class, the conversion would work.

There is a similar question about converting to a class , with the answer being that a derived class can implement an interface and create ambiguity as to whether a custom listing should be used. But there can be no derived type for structures, and the compiler knows that my structure does not implement J.

Is this possible in order to avoid unexpected semantic changes, as interfaces implement new interfaces? Maybe it's just by chance? Maybe I will make a naive mistake? The quote from the specification would be great, but in fact I would like it to be designed this way in the first place.

+4
source share
1 answer

Well, the system cannot perform the actual selection because S<J> does not implement J It works fine if you change your expression:

 public struct S<T> : J {...} 

In the case of classes, you can declare a subtype of the class that implements J But structures cannot be extended, so if S does not implement J , then you can guarantee that no class that "is" S will ever implement J Therefore, no J will never be S<T> .

So why doesn’t it call your explicit casting operator? I think the answer is in the C # specification as described in this SO post .


6.4.1 Allowed custom conversions

C # allows only certain custom conversions to be declared. In particular, it is not possible to override an existing implicit or explicit conversion. For a given type of source S and target type T, if S or T are NULL types, let S0 and T0 belong to their base types, otherwise S0 and T0 are equal to S and T, respectively. A class or structure is allowed to declare a conversion from source type S to destination type T only if all of the following values ​​are true:

  • S0 and T0 are different types.
  • Either S0 or T0 is the type of class or structure in which the operator is declared.
  • Neither S0 nor T0 are a type interface .
  • Excluding custom conversions, the transform does not exist from S to T or from T to S.

So, if I read this right, because J is an interface, it is not recognized as a candidate for your explicit translation operator.

+6
source

Source: https://habr.com/ru/post/1438072/


All Articles