Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this covariance declaration compile? [duplicate]

Consider this interface:

interface Test<out T> where T : struct { }

It compiles without errors or warnings.

As discussed in this question, and mentioned in the Covariance and Contravariance FAQ:

Variance is supported only if a type parameter is a reference type.

So why does the above interface compile? It would make sense to fail (or at least warn) on the "out" keyword. I guess the question boils down to - is there any case where using out keyword in the above example makes any difference?


Update: Here's an example misleading behavior that may slip through for the unaware developer who looks at the Interface above:

typeof(IDummy).IsAssignableFrom(typeof(MyStruct)); // should return true
typeof(ITest<IDummy>).IsAssignableFrom(typeof(ITest<MyStruct>)); // returns false

If the coder isn't aware of variance not working for value types, they would expect the second line to return true - because of the out keyword - but it never will. This is exactly the bug that prompted me to ask this question...


Another example of code that would compile but produce unexpected results:

ITest<MyStruct> foo = ...;
var casted = (ITest<IDummy>)foo;

I would expect this to work (not knowing about the limitation of covariance to reference types) but it causes a System.InvalidCastException.

like image 920
sinelaw Avatar asked May 24 '13 16:05

sinelaw


1 Answers

is there any case where using out keyword in the above example makes any difference?

Nope. You're allowed to specify out in the declaration, you just won't ever be able to actually leverage it when dealing with a specific instance of that type.

Nothing about this program doesn't work properly, so you're essentially asking for a feature request of the compiler prohibiting this behavior as it is a likely indication of a mistake on the part of the developer. The response to that request is (just like virtually any other feature request) that Microsoft either didn't consider this as an option, or if they did, determined that it wasn't worth the time and effort to actively prohibit this behavior.

like image 134
Servy Avatar answered Oct 23 '22 03:10

Servy