17

I watched a video about it on Channel 9 but I didn't really understand it much.

Can someone please give me a simple example about these that's easy to understand? After that maybe how it would be used in practice?

Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • 2
    http://channel9.msdn.com/ - A collection of videos about microsoft development frameworks, and a lot more :) – cwap Nov 12 '09 at 19:56
  • Yeah it's like a podcast, has some really good c# vids with Anders, etc. – Joan Venge Nov 12 '09 at 19:58
  • http://stackoverflow.com/questions/1078423/c-is-variance-covariance-contravariance-another-word-for-polymorphism should answer a lot of your questions about it (also see Jon Skeet's link to Eric Lippert's blog. – Matt Ball Nov 12 '09 at 19:58

5 Answers5

9

You may want to look at this blog, he does a fantastic job of explaining it, but I think it will take more examples to clear it up for people, as this gets into a very hard-to-understand area, but, the quote below from the article sums it up well.

http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html

"covariance and contravariance" means that you can now pass inexact generic types when it's safe to do so, just as you can pass inexact argument types when it's safe to do so.

James Black
  • 41,583
  • 10
  • 86
  • 166
8

A Tiger IS an Animal so it can do anything an Animal can do. If I have a method that asks for an Animal I can also pass in a Tiger.

Covariance - Passing a more specific type argument

This is the direction you are most familiar with. I can pass an IEnumerable<Tiger> anywhere that expects an IEnumerable<Animal>.


static void ListAnimals(IEnumerable<Animal> animals)
{
}

List<Tiger> tigers = new List<Tiger>();
ListAnimals(tigers);

Contravariance - Passing a more general type argument.

The 'contra' implies that this goes 'against' the normal conversion flow . This one is trickier because it seem's counter-intuitive until you see it in action.

Say I have a function which expects an IComparer<Tiger> and two tigers to be compared. Contravariance says I can also pass in the more general IComparer<Animal> because it can also compare two tigers (since a Tiger IS an animal). It compares them in a more general way, but this is still type safe.


static void CompareTigers(IComparer<Tiger> comparer, Tiger tiger1, Tiger tiger2)
{
    comparer.Compare(tiger1, tiger2);
}

// normal - a tiger comparer can compare two tigers
IComparer<Tiger> tigerComparer = null;
CompareTigers(tigerComparer, new Tiger(), new Tiger());

// contravariance - an animal comparer can ALSO compare two tigers
IComparer<Animal> animalComparer = null;
CompareTigers(animalComparer, new Tiger(), new Tiger());

Note that this also works with delegates. I can pass an Action<Animal> into a function that expects an Action<Tiger> because Tiger objects can also be passed safely to the Action<Animal> delegate.

Despertar
  • 21,627
  • 11
  • 81
  • 79
3

Eric Lippert came up with a very good explanation in a recent blog post

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
1

The following article deals with co- and contravariance with delegates: http://msdn.microsoft.com/en-us/library/ms173174.aspx.

Perhaps it is useful to you, even if you're not into delegates yet. I found it to be quite easy to understand.

Webleeuw
  • 7,222
  • 33
  • 34
1

MSDN docs for C# 4.0 (and VB) are here: Covariance and Contravariance

If you are interested in concrete examples, they are here:

Alexandra Rusina
  • 10,991
  • 2
  • 20
  • 16