Co-variant array conversions

Here’s one of my favorite programming questions: let’s say, in a C# program, we have a parent class

class Book
	public void Read() { Console.WriteLine("Reading..."); }

and a child class

class EBook : Book
    public void Download() {  Console.WriteLine("Downloading... "); }

In other words, EBook is a Book (a more special one - it can be downloaded).

Will the following code compile or not?

EBook[] eBooks = new EBook[10];
Book[] books = eBooks;  

I like this question, because when I heard it first, I went through the following thinking process:

  • Since an EBook is a Book, we should be able to use it wherever only a Book is required. We can always provide the more special type. So, probably the answer is “yes”.

  • However, although an EBook is a Book, that doesn’t automatically mean that an array of EBooks is an array of Books. In fact, there’s a problem with that: if the compiler will accept the conversion above, one could do this next:

books[0] = new Book()

Whoops - now we’ve inserted a new element into the array which is just a Book, not an eBook. So, if we now try to do this with the eBooks reference to the same array…


… it won’t work - the Download method is not defined on the parent type. So, the answer must be “no”!

Well - turns out the right answer is actually “yes”: the code will compile.

The reason for that is that C# (and also Java) supports covariant array conversions. It basically means that if B is a subtype of A, an array of B will also be treated as a subtype of A and array insertions are checked at runtime. So, while the example above will compile, the assignment to books[0] will throw an ArrayTypeMismatchException.

Things get more complicated with generic containers such as Lists (covariant/contravariant type parameters in C#, and the notorious wildcard types in Java…), but that’s kinda expected.

For more, I recommend the Wikipedia article on Covariance and contravariance. It’s an interesting topic which tends to fry even the brains of experienced programmers.

Written on March 22, 2016.