What does "From any class-type S to any interface-type T, provided S is not sealed and pr开发者_如何学运维ovided 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 advance.
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(); // S reference to an S2 instance, implicit conversion
T t = (T)s; // OK, s refers to an S2 instance that does implement T
Could it be that it is in the specs only to enumerate all syntactically correct ways of expressing an explicit reference conversion, ...
Yes, the compiler must allow it unless it knows the conversion to be impossible.
If you 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).
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).
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.
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.
精彩评论