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?
Eric Lippert came up with a very good explanation in a recent blog post
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.
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.
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.
MSDN docs for C# 4.0 (and VB) are here: Covariance and Contravariance
If you are interested in concrete examples, they are here:
Using Variance in Interfaces for Generic Collections
Using Variance in Delegates
Using Variance for Func and Action Generic Delegates