#571 – Covariance in Programming Languages

In programming languages, the idea of covariance has to do with whether the ordering of a set of elements is preserved after calling some function that transforms each element.

Consider a set of elements and a function F that accepts as input a member of the set and returns a member of the set.  I.e. X’ = F(X), where both X and X’ are members of the set.

We describe a function as covariant if preserves the ordering of elements of the set passed to it.  If we have two members of our set, X and Y, and X <= Y, then the function F is covariant if F(X) <= F(Y).

For example, the function F(X) = 2X is covariant with respect to the set of integers.  If X <= Y, then 2X <= 2Y, for any X and Y integer values that you pick.

#568 – Array Covariance

In C#, you can always implicitly convert an instance of a more derived type  to an instance of a base type.

For example, the following is allowed:

Hound huck = new Hound("Huckleberry", 55);

// Since Hound is a sub-class of Dog, we can
// assign to Dog
Dog someDog = huck;

Note that at this point, the someDog variable points to an instance of a Hound, rather than an instance of a Dog.

You can also assign an array of objects of a more derived type to an array of objects of a base type.  This is known as array covariance.  It’s allowed as long as the type of the source array elements is implicitly convertible to the type of the target array elements.

Hound[] hounds = new Hound[2] {
new Hound("Huckleberry", 55),
new Hound("Astro", 50)};

// Allowed because of array covariance
Dog[] dogs = hounds;