I am having trouble understanding the difference between covariance and contravariance.
Co and Contra variance are pretty logical things. Language type system forces us to support real life logic. It's easy to understand by example.
For instance you want to buy a flower and you have two flowers shop in your city: rose shop and daisy shop.
If you ask someone "where is the flowers shop?" and someone tells you where is rose shop, would it be okay? Yes, because rose is a flower, if you want to buy a flower you can buy a rose. The same applies if someone replied you with the address of the daisy shop.
This is example of covariance: you are allowed to cast A
to A
, where C
is a subclass of B
, if A
produces generic values (returns as a result from the function). Covariance is about producers, that's why C# use keyword out
for covariance.
Types:
class Flower { }
class Rose: Flower { }
class Daisy: Flower { }
interface FlowerShop where T: Flower {
T getFlower();
}
class RoseShop: FlowerShop {
public Rose getFlower() {
return new Rose();
}
}
class DaisyShop: FlowerShop {
public Daisy getFlower() {
return new Daisy();
}
}
Question is "where is the flower shop?", answer is "rose shop there":
static FlowerShop tellMeShopAddress() {
return new RoseShop();
}
For instance you want to gift a flower to your girlfriend and your girlfrend likes any flowers. Can you consider her as a person who loves roses, or as a person who loves daisies? Yes, because if she loves any flower she would love both rose and daisy.
This is an example of the contravariance: you’re allowed to cast A
to A
, where C
is subclass of B
, if A
consumes generic value. Contravariance is about consumers, that's why C# use keyword in
for contravariance.
Types:
interface PrettyGirl where TFavoriteFlower: Flower {
void takeGift(TFavoriteFlower flower);
}
class AnyFlowerLover: PrettyGirl {
public void takeGift(Flower flower) {
Console.WriteLine("I like all flowers!");
}
}
You're considering your girlfriend who loves any flower as someone who loves roses, and giving her a rose:
PrettyGirl girlfriend = new AnyFlowerLover();
girlfriend.takeGift(new Rose());