C# 4.0 is going to support covariance and contravariance. But I don't clearly understand the benefits of this new feature. Can you explain me (clearly) why we need it?
-
Bart De Smet has a great blog entry about covariance & contravariance [here](http://bartdesmet.net/blogs/bart/archive/2009/04/13/c-4-0-feature-focus-part-4-generic-co-and-contra-variance-for-delegate-and-interface-types.aspx). – Mike Thompson Sep 11 '09 at 03:19
4 Answers
They just allow you to do some things that are conceptually valid, and formally acceptable, but aren't currently allowed because of language constraints. For example:
IEnumerable<int> ints = new List<int> { 1, 2, 3 };
Action<IEnumerable<object>> PrintThings =
x => { foreach(var thing in x) Console.WriteLine(thing); };
PrintThings(ints); // doesn't compile right now :( will compile in 4.0
There's no fundamental reason why this can't work or shouldn't work; it just happens to not be allowed in the language. By allowing it, you make programmers' lives easier when such an operation would be natural for them to perform.

- 70,359
- 14
- 95
- 123
-
The fundamental reason the above won't work before 4.0 is that there is no way in the syntax to allow it without losing type safety. If you allow it for your example, then you necessarily also allow it for examples where type safety is not preserved. – Eddie Apr 29 '09 at 17:42
-
That's right, which is why they're adding the new "in" and "out" keywords to support it (and IEnumerable
will be – mqp Apr 29 '09 at 18:12to allow this scenario.)
There are alot of misconceptions out there as to how and what will work in 4.0. The best explanation I've read so far was written my Marc Gravell. See his blog post here:
http://marcgravell.blogspot.com/2009/02/what-c-40-covariance-doesn-do.html
Just to reiterate, alot of ppl think this will work in 4.0:
public class Base{}
public class Derived : Base {}
..in some other class
List<Derived> derived....
public void Method(List<Base> b){}
Even in 4.0, you will not be able to pass the List into this method. As Marc points out, that's what Generic constraints are there for, and can be done since 2.0

- 102,548
- 21
- 159
- 201
-
This seems like a strange non sequitur to me. The only reason you can't pass the List is because Lists are mutable; of course you can't pass like that, since adding items to it would break the type restrictions on it. – mqp Apr 29 '09 at 16:04
-
@mquander: A strange non-sequitur? The API (pre 4.0) has nothing to say, "you can do this operation only if the object is immutable". – Eddie Apr 29 '09 at 17:40
-
My point is simply that the fact that List
allows you to add and change Ts is why it doesn't make sense. If you tried to add the "out" parameter on IList – mqp Apr 29 '09 at 18:16to allow this, those methods could no longer work as intended.
One of the benefits that, in my opinion, covariance is going to help a lot is with Generics.
I encountered several situations where one needs to explicitly use Cast
to convert a specific type to it's base.
class Foo { }
class Bar : Foo { }
// ...
IEnumerable<Foo> foos = new List<Foo>();
IEnumerable<Bar> bars = new List<Bar>();
foos = bars.Cast<Foo>();
// C# 4.0
foos = bars;
Here's a good reference on the subject.

- 47,767
- 15
- 98
- 117