109

I didn't attend PDC 2008, but I heard some news that C# 4.0 is announced to support Generic covariance and contra-variance. That is, List<string> can be assigned to List<object>. How could that be?

In Jon Skeet's book C# in Depth, it is explained why C# generics doesn't support covariance and contra-variance. It is mainly for writing secure code. Now, C# 4.0 changed to support them. Would it bring chaos?

Anybody know the details about C# 4.0 can give some explanation?

Daniel May
  • 8,156
  • 1
  • 33
  • 43
Morgan Cheng
  • 73,950
  • 66
  • 171
  • 230
  • Here is a good article that covers the upcoming covariance and contra-variance implementations on delegates and interfaces in C# 4.0: [LINQ Farm: Covariance and Contravariance in C# 4.0](http://blogs.msdn.com/charlie/archive/2008/10/28/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx) – Christian C. Salvadó Oct 29 '08 at 02:32
  • Anders Noråse explains in [C# 4.0 - Covariance and contra-variance](http://web.archive.org/web/20100227031805/http://andersnoras.com/post/100795246/c-4-0-covariance-and-contra-variance) the concept and shows, that it's already supported today in IL since .NET 2.0. – Thomas Freudenberg Oct 30 '08 at 09:20

2 Answers2

158

Variance will only be supported in a safe way - in fact, using the abilities that the CLR already has. So the examples I give in the book of trying to use a List<Banana> as a List<Fruit> (or whatever it was) still won't work - but a few other scenarios will.

Firstly, it will only be supported for interfaces and delegates.

Secondly, it requires the author of the interface/delegate to decorate the type parameters as in (for contravariance) or out (for covariance). The most obvious example is IEnumerable<T> which only ever lets you take values "out" of it - it doesn't let you add new ones. That will become IEnumerable<out T>. That doesn't hurt type safety at all, but lets you return an IEnumerable<string> from a method declared to return IEnumerable<object> for instance.

Contravariance is harder to give concrete examples for using interfaces, but it's easy with a delegate. Consider Action<T> - that just represents a method which takes a T parameter. It would be nice to be able to convert seamlessly use an Action<object> as an Action<string> - any method which takes an object parameter is going to be fine when it's presented with a string instead. Of course, C# 2 already has covariance and contravariance of delegates to some extent, but via an actual conversion from one delegate type to another (creating a new instance) - see P141-144 for examples. C# 4 will make this more generic, and (I believe) will avoid creating a new instance for the conversion. (It'll be a reference conversion instead.)

Hope this clears it up a bit - please let me know if it doesn't make sense!

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    So, does it mean that if the class is declared as "List" then it should NOT have a member function like "void Add(T obj)"? The C# 4.0 compiler will report error on that, right? – Morgan Cheng Oct 30 '08 at 01:24
  • 1
    Morgan: That's certainly my understanding, yes. – Jon Skeet Oct 30 '08 at 22:10
  • 4
    yet again one of your answers here on SO has immediately helped me improve some code. Thank you! – Mark Oct 08 '10 at 12:34
  • @Ark-kun: Yes, I'm aware of that. Hence the "still won't work" in the same sentence. (And I'm aware of the reasons, too.) – Jon Skeet Jun 09 '13 at 07:27
  • @JonSkeet Is it correct that "you can only use a `List` as an `IList`" as @Ark-kun said? If so, how is this possible, although the type parameter of the [`IList`](http://msdn.microsoft.com/en-us/library/5y536ey6(v=vs.110).aspx) interface is not defined as covariant (no `out T`, but simply `T`). – gehho Oct 23 '13 at 12:48
  • @gehho: No, you can't - you can use it as an `IEnumerable` though. I'm surprised I didn't pick up on that when the comment was written... – Jon Skeet Oct 23 '13 at 12:49
  • @JonSkeet Alright, got it. Was happy that I finally understood the generic covariance thing, and then I saw this one... :) Thanks for the fast response! – gehho Oct 23 '13 at 13:01
  • @gehho So, there was another error in my comment... Deleted the comment to prevent future confusion. – Ark-kun Oct 23 '13 at 18:03
6

Not that Jon hasn't already covered it, but here are some links to blogs and videos from Eric Lippert. He does a nice job of explaining it with examples.

https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/

The videos:

https://www.youtube.com/watch?v=3MQDrKbzvqU

https://www.youtube.com/watch?v=XRIadQaBYlI

https://www.youtube.com/watch?v=St9d2EDZfrg

kemiller2002
  • 113,795
  • 27
  • 197
  • 251