Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is Generic Covariance & Contra-variance Implemented in C# 4.0?

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?

like image 516
Morgan Cheng Avatar asked Oct 29 '08 02:10

Morgan Cheng


People also ask

What is the exact meaning of generic?

A generic type is a generic class or interface that is parameterized over types.

What is difference between covariance and Contravariance?

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.

What is covariance Java generics?

Covariance can be translated as "different in the same direction," or with-different, whereas contravariance means "different in the opposite direction," or against-different. Covariant and contravariant types are not the same, but there is a correlation between them. The names imply the direction of the correlation.

How do you declare a generic interface as contravariant?

You can declare a generic type parameter contravariant by using the in keyword. The contravariant type can be used only as a type of method arguments and not as a return type of interface methods. The contravariant type can also be used for generic constraints.


2 Answers

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!

like image 77
Jon Skeet Avatar answered Oct 16 '22 10:10

Jon Skeet


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

like image 43
kemiller2002 Avatar answered Oct 16 '22 10:10

kemiller2002