What is the meaning of the concepts 'covariance' and 'contravariance'?
Given 2 classes, Animal and Elephant (which inherits from Animal), my understanding is that you would get a run-time errors if you try and put an Elephant into an array of Animals, and this happens because Elephant is "bigger" (more specific) than Animal. But could you place an Animal into an array of Elephant, seeing how Elephant is guaranteed to contain the Animal properties?
You should try reading pages 45-49 of Introducing .NET 4.0 With Visual Studio 2010 which deals with this exact example. It even has some nice photos of elephants.
The main point to take out is, to do this
with:
you need the "out" in the interface definition, which will allow more specific forms to be set, but anything read out of IThing must be guaranteed to be the more general type.
You have it backwards. You can add an Elephant to an Animal array because it is an Animal, and it's guaranteed to have all of the methods an Animal is required to have. You can't add an Animal to an Elephant array because it does not have all of the methods that an Elephant is required to have.
The Wikipedia article on covariance and contravariance has a good explanation of this:
Also, you said that type Elephant was "bigger", and this is not the case. Type Animal is "bigger" in the sense that it includes more specific types, such as Elephant, Giraffe, and Lion.
Have a look at this overview of covariance and contravariance in C# 4.0 and see if that helps:
http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx