44

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 ?

Andreas Grech
  • 105,982
  • 98
  • 297
  • 360

5 Answers5

70

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Ah yes infact I was reading Lippert's posts, and found them quite helpful – Andreas Grech Jul 03 '09 at 09:07
  • 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 Jul 03 '09 at 09:08
  • Nope, there was another one in the series very recently ("The void is invariant") – Jon Skeet Jul 03 '09 at 09:09
  • 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 Jul 03 '09 at 09:14
  • I'll do a bit more editing to get rid of the claim that it doesn't work :) – Jon Skeet Jul 03 '09 at 10:33
  • All links currently result in 404, so here's an updated link for Eric Lippert's blog series, https://ericlippert.com/2007/10/16/covariance-and-contravariance-in-c-part-1/. – ethane Mar 22 '22 at 21:02
  • @ethane: Please edit changes like that in directly. I'll do it now, but it would have been easy for you to do instead. – Jon Skeet Mar 22 '22 at 21:03
49

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.

Glory Raj
  • 17,397
  • 27
  • 100
  • 203
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • so would it be accurate to say that (co|contra)variance are mechanisms by which you achieve polymorphism? – John Smith Oct 04 '15 at 21:53
  • @EricLippert...SO WHAT YOUR SAYING IS....its polymorphic at the generic level but not polymorphic at the specific level ;) I say its raining Cats & Dogs as long as `Rain(T:Animal)` – GoldBishop Jul 19 '17 at 17:31
21

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
  • 48,631
  • 24
  • 141
  • 189
  • In your covariance example, shouldn't it be `void FeedAll(ICollection pets)` instead of `ICollection`? – Ray May 11 '10 at 21:09
  • I like your post better....more color and code examples. I like the pretty pictures ;) So `CoVariance` is evaluated by inheritence and `ContraVariance` is evaluated the other way....as in `Contradictory`? – GoldBishop Jul 19 '17 at 17:35
-2

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
  • 743
  • 2
  • 8
  • 22
  • 1
    no it's aspects of polymorphism in function parameters and return values. this means it affects delegates but it doesn't require them – ShuggyCoUk Jul 03 '09 at 09:13