6

Before C# 4.0 came out, I was quite excited about covariance and contravariance. It pandered to my fondness for theoretical correctness!

However, now that it’s out, and I’m back to writing normal, everyday, boring code, I’m starting to wonder: did I ever use it yet? And I notice that I haven’t used it consciously. None of the interfaces or delegates I have defined since have benefited from it.

There is only one single case in which I later discovered I unwittingly used covariance, but it’s very subtle and I could as well have not noticed it. Imagine X is a base-class and Y is a descendent of it:

if (enumerableOfYs.Contains(variableOfTypeX))

Are there any interesting or exciting examples where any of you guys have used covariance or contravariance in a real-life, non-contrived use-case and it has really saved the day by being spectacularly “correct”?

Timwi
  • 65,159
  • 33
  • 165
  • 230
  • 5
    You mean besides things like `IEnumerable`, `Func`, and `IComparable` that you probably use everyday without realizing it? – Gabe Aug 27 '10 at 05:10

4 Answers4

9

The only "real world" use of variance that I've run into in my actual writing-programs-for-customers (as opposed to writing compiler test cases or articles or whatever) is I now can pass an IEnumerable<TypeParameterDefinedInSource> to a method that expects an IEnumerable<TypeSymbol> when I write code analysis tools in C#.

It's really not a "save the day" sort of feature. It's more of a "it works the way I expect it to" feature.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Hi, Eric. Thanks for your answer. This leads me to a more general question though: How does the C# team prioritise features? How come that a feature that doesn’t “save the day” get so much more priority than features that would *both* “save the day” *and also* make things “work the way I expect them to”? (e.g. generic custom attributes, anonymous iterator blocks, etc.) – Timwi Aug 29 '10 at 07:41
  • 3
    @Timwi: We prioritize features based on a long list of competing criteria, including factors like difficulty of implementation, how well it works with or against other features, whether it fits into the broader theme for the release, and so on. Variance was easy; we knew how to implement it, it was already supported in the CLR, we understand the theory extremely well and it removed a genuine customer problem that is reported all the time. A larger feature would have taken away too many resources from making "dynamic" work which was the high order bit for the release. – Eric Lippert Aug 29 '10 at 14:16
  • I think "It's more of a "it works the way I expect it to" feature" is the key to way it is so useful. – Ian Ringrose Sep 29 '10 at 10:36
  • Another nice use for variance is with interfaces in which an object's method will return something of the object's own type (common examples being a clone method or return-self-as-type method). If a class implements ICloneable(Of DerivedType), it can automatically be invoked by something expecting an ICloneable(Of BaseType), without having to implement a separate ICloneable(Of WhateverType) for every type it handles. – supercat Dec 13 '10 at 23:54
3

I viewed the excellent two-part video series on covariance and contravariance by Eric Lippert, one of the designers of the feature. The videos contain the clearest explanation I can find of how the feature works; however, the examples are contrived for the demonstration.

I especially appreciated Eric's discussion at the end of the second video about when he expected users would use the feature. He indicated that most line-of-business application developers probably would not create many interfaces employing covariance or contravariance, but that it is more likely the role of a framework developer (including your own frameworks, of course).

On the other hand, I can finally place an IEnumerable<DerivedClass> into a method expecting an IEnumerable<BaseClass> without jumping through type casting hoops myself. Eventually, I'll probably forget that I ever couldn't. I think this will be the most compelling and common usage of covariance/contravariance: super-subtle things that just work when, in earlier versions of .NET, they didn't.

kbrimington
  • 25,142
  • 5
  • 62
  • 74
1

Features like covariance and contravariance don't really "save the day." Rather, when used correctly, they make later maintenance easier. In this way, it's much like const correctness in C++. It doesn't add any power, but code written correctly uses it and it makes the system much easier to work with.

NOTE: I haven't used it yet because I just upgraded to VS 2010.

tster
  • 17,883
  • 5
  • 53
  • 72
  • Hm, I disagree. Const in C++ is a restriction. Covariance/contravariance is the opposite, it’s an extra ability. – Timwi Aug 27 '10 at 05:11
  • @Timwi, yes that's a good point. It does add a lot of value. I was wrong. – tster Aug 27 '10 at 05:20
0

I used C# for about three years, and I only recall ever "missing" variance features maybe once or twice.

It's possible that now that they're in the language, I'll find more opportunities to take advantage of them, but I do think they are 'minor' features at best.

(I'm interested to see what others answers appear here.)

Brian
  • 117,631
  • 17
  • 236
  • 300