Now, to my unprepared look, covariance seems to be the same as a raise, except that it refers to casting collections. (And a similar statement can be made regarding contravariance and downgrade).
It's really that simple?
Covariance is not associated with an increase, although I can understand why you think it is related.
Covariance concerns the following very simple idea. Let's say you have a derivedSequence variable of type IEnumerable<Derived> . Say you have a baseSequence variable of type IEnumerable<Base> . Here Derived comes from Base . Then, with covariance, the following legal purpose, and the link is implicitly addressed:
baseSequence = derivedSequence;
Please note that this does not go up. This is not the case when IEnumerable<Derived> comes from IEnumerable<Base> . Rather, it is covariance that allows you to assign the value of the derivedSequence variable to the baseSequence variable. The idea is that variables of type Base can be assigned from objects of type Derived , and since IEnumerable<T> is covariant in its parameter, objects of type IEnumerable<Derived> can be assigned variables of type IEnumerable<Base> .
Of course, I have not yet explained what covariance is. In general, covariance refers to the following simple idea. Let's say you have a mapping F from type to type (I will denote this mapping with F<T> , given the type T its image in the map F is F<T> .) Let's say that this map has the following special property:
if X is an assignment compatible with Y , then F<X> also compatible with F<Y> .
In this case, we say that F covariant in its parameter T (Here, to say that β A is an assignment compatible with B β where A and B are reference types, means that instances of B can be stored in variables of type A )
In our case, IEnumerable<T> in C # 4.0 is an implicit reference conversion from instances of IEnumerable<Derived> to IEnumerable<Base> if Derived derived from Base . The direction of assignment compatibility is preserved, and so we say that IEnumerable<T> is covariant in its type parameter.