views:

53

answers:

4

What does "From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T." actually mean?

I came across this in the C# Language Specifications here:

6.2.4 Explicit reference conversions

The explicit reference conversions are:

  • ...
  • From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.

I can understand what "provided S is not sealed" means, but I'm not sure if I understand what "provided S does not implement T" really mean.

For example:

class S {}//not sealed, nor does it implement T
interface T {}
...
T t = (T)new S();//will throw InvalidCastException.

Could it be that it is in the specs only to enumerate all syntactically correct ways of expressing an explicit reference conversion, regardless of whether it will throw an exception or not? Or does it mean some other thing which I do not know (as of now)?

Thanks in advanced.

A: 

Are you sure it's not an error in the text?

Provided S does implement T.

Edit: I've found the reference: http://msdn.microsoft.com/en-us/library/aa691291(v=VS.71).aspx

That is explicit reference conversion, it means that is not implicit! So the sentence "From any class-typeS to any interface-typeT, provided S is not sealed and provided S does not implement T" is correct, it can't be an implicit conversion, so it must be explicit (and is not guaranteed it would succeed).

vulkanino
I thought it could be an error. However it may just be the case that I simply do not know how to interpret it correctly, considering the analogy of "it's most likely a bug in your code and not in the compiler."
blizpasta
+4  A: 

The pun is in the "not sealed" part:

class S {} //not sealed, nor does it implement T
interface T {}

class S2 : S, T { }

  S s = new S2();
  T t = (T)s; // OK

Could it be that it is in the specs only to enumerate all syntactically correct ways of expressing an explicit reference conversion, ...

Yes, the compile must allow it unless it knows the conversion to be impossible.

If you only look at T t = (T)s;, if S was sealed then the compiler could know with certainty that the conversion was impossible. But with an unsealed S, it would have to eliminate the possibility that s is referencing an S2 type, and that is not practical/possible (S2 could be in another assembly).

Henk Holterman
_ lol, the not sealed part indeed told that inheritance **is** involved. Did not see that instantly ;). great lesson on explicit reading!
Caspar Kleijne
Thanks! Doubt I'll be able to get that by myself.
blizpasta
A: 

It seems it's all about user-defined conversions.

You definitely can't cast class S to interface T if S does not implement T.

Dmitry Karpezo
User-defined conversions are irrelevant here. Just because you have a reference to an object that acts as S, does not mean it is exactly an S and not something that is superset of S. That superset might be convertible with the standard conversion rules to T.
Franci Penov
A: 

The spec goes to say:

The explicit reference conversions are those conversions between reference-types that require run-time checks to ensure they are correct.

In other words, the types of conversion listed here are those explicit conversion, where the compiler cannot make the check if such conversion is possible and valid at compile time, due to a lack of explicit relationship between the two types. Such conversion attempt will be resolved during the execution of the program and might result in an exception, if the conversion is impossible.

The canonical example of a run-time explicit conversion that might fail, but also might succeed, would be conversion from interface-type S to interface-type T, where S and T are not related. The success depends on whether the underlying object implements both interfaces or not.

Particular curious example of the case you asked about - from class-type S to interface-type T, where S does not implement T (and is not sealed), would be when S is a COM object, and T is a COM interface not explicitly listed in the type library as implemented by the coclass. In this case, the conversion might fail, but it also might succeed, depending on what the particular IUnknown::QueryInterface implementation of the coclass is. (Note that technically, the coclass in this case is implementing the interface, but is not advertising it to the compiler)

And of course, @Henk Holterman example of S2 : S, T is also a good example where that conversion can succeed.

Franci Penov