7

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.

Community
  • 1
  • 1
sinelaw
  • 16,205
  • 3
  • 49
  • 80

1 Answers1

2

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.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • If that's the case, I consider it a bug in the compiler. It shouldn't allow using variance keywords when they have no effect. – sinelaw May 24 '13 at 16:19
  • 1
    @sinelaw: I agree with you. My fault. I never even considered this when we were designing the feature. See http://stackoverflow.com/questions/9353293/c-sharp-variance-annotation-of-a-type-parameter-constrained-to-be-value-type for my mea culpa. – Eric Lippert May 24 '13 at 16:24
  • @EricLippert, thanks! As you said "...maybe there are developers out there who might type this in thinking that it will work" - I guess that was me. :) – sinelaw May 24 '13 at 16:28
  • @sinelaw: You're welcome. I never did get this warning in. I've just sent a note to the Roslyn team suggesting that they add it before Roslyn ships. – Eric Lippert May 24 '13 at 16:29
  • @sinelaw The primary point against it in my mind is that you'll still be getting *compile time* errors if you actually tried to use covariance on this type. You'll be getting those compile time errors a bit down the road, but it's not like they'll end up being runtime errors. Would it be nice if we could just get this behavior for free, yes, absolutely, but is it worth the time and effort it would take; possibly, but I'm inclined to think not. – Servy May 24 '13 at 16:33
  • @Servy, see the code in the updated question - it's based on real code from production that caused a bug. If you're doing reflection trickery and using `IsAssignableFrom`, you can hit it without getting compile errors. – sinelaw May 24 '13 at 16:39