This question already has an answer here:
While reading a section of an article about covariance and contravariance at Wikipedia, I ran into the following, bolded sentence:
First consider the array type constructor: from the type
Animal
we can make the typeAnimal[]
("array of animals"). Should we treat this as
- Covariant: a
Cat[]
is aAnimal[]
- Contravariant: a
Animal[]
is aCat[]
- or neither (invariant)?
If we wish to avoid type errors, and the array supports both reading and writing elements, then only the third choice is safe. Clearly, not every
Animal[]
can be treated as if it were aCat[]
, since a client reading from the array will expect a Cat, but anAnimal[]
may contain e.g. aDog
. So the contravariant rule is not safe.Conversely, a
Cat[]
can not be treated as aAnimal[]
. It should always be possible to put aDog
into aAnimal[]
. With covariant arrays this can not be guaranteed to be safe, since the backing store might actually be an array of cats. So the covariant rule is also not safe—the array constructor should be invariant. Note that this is only a issue for mutable arrays; the covariant rule is safe for immutable (read-only) arrays.
I understand the concept; I just want an example of how this "cannot be guaranteed to be safe" in C#.
I think what they're trying to say is:
Line 3 of this code cannot be legal because you SHOULD always be able to do line 4 (Adding a
Dog
to an array ofAnimal
s). But if line 3 was legal, then line 4 would not be legal (because you can't add aDog
to an array ofCat
s).It's not safe at compile time. In other words, there's code which is legal by the language rules, but fails at execution time, without any explicit casting to give a big warning sign of "this might fail". The CLR makes sure that only valid writes succeed at execution time. For example:
That will throw an exception (
ArrayTypeMismatchException
) at execution time. The alternative would have been to allow it at execution time, at which pointstrings[0]
would have been a reference to a non-string object, which would clearly be bad.See also recent blog posts: