views:

1234

answers:

5

I am trying to figure out the exact meaning of the words Covariance and Contravariance from several articles online and questions on StackOverflow, and from what I can understand, it's only another word for polymorphism.

Am I correct with the above statement? Or have I got it wrong ?

+19  A: 

It's certainly related to polymorphism. I wouldn't say they're just "another word" for polymorphism though - they're about very specific situations, where you can treat one type as if it were another type in a certain context.

For instance, with normal polymorphism you can treat any reference to a Banana as a reference to a Fruit - but that doesn't mean you can substitute Fruit every time you see the type Banana. For example, a List<Banana> can't be treated as a List<Fruit> because list.Add(new Apple()) is valid for List<Fruit> but not for List<Banana>.

Covariance allows a "bigger" (less specific) type to be substituted in an API where the original type is only used in an "output" position (e.g. as a return value). Contravariance allows a "smaller" (more specific) type to be substituted in an API where the original type is only used in an "input" position.

It's hard to go into all the details in a single SO post (although hopefully someone else will do a better job than this!). Eric Lippert has an excellent series of blog posts about it.

Jon Skeet
Ah yes infact I was reading Lippert's posts, and found them quite helpful
Andreas Grech
The blog posts were all published in October 2007, I think, so they are available on this page: http://blogs.msdn.com/ericlippert/archive/2007/10.aspx
Fredrik Mörk
Nope, there was another one in the series very recently ("The void is invariant")
Jon Skeet
Eric's posts on this are awesome. Might I suggest adding in to the answer a list of said links since his blog software is not working on the tags.
ShuggyCoUk
@ShuggyCoUk: I edited Jon's answer so the link works now.
Fredrik Mörk
awesome, cheers Fredrik
ShuggyCoUk
I'll do a bit more editing to get rid of the claim that it doesn't work :)
Jon Skeet
A: 

I think is is special kind of polymorphism not another word for it. It is polymorphism in delegates where a delegate with a return type of base can accept child type.

Sali Hoo
no it's aspects of polymorphism in function parameters and return values. this means it affects delegates but it doesn't require them
ShuggyCoUk
+9  A: 

You can think about co- and contravariance as being an advanced form of polymorphism. Not only can you use a child-class as if it was its parent-class, with co- and contravariance, the polymorphism extends to classes that relates to the polymorphic classes.

Imagine two classes:

public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }

Polymorphism is being able to use a Cat as a Pet:

void Feed(Pet pet) { /* ... */ }

Cat cat = ...
Feed(cat);

Co- and contravariance is used to talk about being able to use an ICollection<Cat> as an ICollection<Pet> (covariance):

void FeedAll(ICollection<Pet> pets) { /* ... */ }

List<Cat> cats = ...
FeedAll(cats);

or to use an Action<Pet> as an Action<Cat> (contravariance):

Action<Pet> GetFeeder() { /* ... */ }

Action<Cat> feeder = GetFeeder();

Eric Lippert wrote a great blog series about it when they were first designing the feature. Part one is here.

Rasmus Faber
In your covariance example, shouldn't it be `void FeedAll(ICollection<Pet> pets)` instead of `ICollection<Cat>`?
Ray Vega
@Ray Thanks. Fixed.
Rasmus Faber
+11  A: 

Thanks for all the shout-outs, guys.

Jon and Rasmus's answers are fine, I would just add a quick technical note.

When speaking casually and informally, yes, people use "covariance" and "contravariance" to refer to a specific kind of polymorphism. That is, the kind of polymorphism where you treat a sequence of spiders as though it were a sequence of animals.

Were we to get all computer-sciency and try to make more technical definitions, then I probably would not say that covariance and contravariance are "a kind of polymorphism". I would approach a more technical definition like this:

First, I'd note that there are two possible kinds of polymorphism in C# that you might be talking about, and it is important to not confuse them.

The first kind is traditionally called "ad hoc polymorphism", and that's the polymorphism where you have a method M(Animal x), and you pass spiders and giraffes and wallabies to it, and the method uniformly treats its passed-in arguments the same way by using the commonalities guaranteed by the Animal base class.

The second kind is traditionally called "parametric polymorphism", or "generic polymorphism". That's the ability to make a generic method M<T>(T t) and then have a bunch of code in the method that again, treats the argument uniformly based on commonalities guaranteed by the constraints on T.

I think you're talking about the first kind of polymorphism. But my point is just that we can define polymorphism as the ability of a programming language to treat different things uniformly based on a known commonality. (For example, a known base type, or known implemented interface.)

Covariance and contravariance is the ability of a programming language to take advantage of commonalities between generic types deduced from known commonalities of their type arguments.

Eric Lippert