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?
In C#, covariance and contravariance enable implicit reference conversion for array types, delegate types, and generic type arguments. Covariance preserves assignment compatibility and contravariance reverses it.
This is mainly useful when using already defined standard interfaces. Covariance means that you can use IEnumerable<string> in place where IEnumerable<object> is expected. Contravariance allows you to pass IComparable<object> as an argument of a method taking IComparable<string> .
Covariance permits a method to have return type that is more derived than that defined in the delegate. Contravariance permits a method that has parameter types that are less derived than those in the delegate type.
Covariance permits a method to have a return type that is a subtype of the one defined in the delegate. Contravariance permits a method to have a parameter type that is a base type of the one defined in the delegate type.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With