Difference between covariance and increase

What is the difference between covariance and promotion, or rather, why are they given different names?

I saw the following example, called "promotion":

string s = "hello"; object o = s; //upcast to 'string' to 'object' 

While the following I saw is called "covariance":

 string[] s = new string[100]; object[] o = s; IEnumerable<string> ies = new List<string>(); IEnumerable<object> ieo = ies; 

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?

+59
casting c # covariance
Jul 15 2018-11-17T00:
source share
6 answers

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.

+57
Jul 15 '11 at 13:32
source share
β€” -

Casting refers to changing the static type of objects and expressions.

Deviation refers to the interchangeability or equivalence of types in certain situations (such as parameters, generics, and return types).

+18
Jul 15 '11 at 13:27
source share

IEnumerable<string> not inferred from IEnumerable<object> , so casting between them does not increase. IEnumerable is covariant in its type parameter, and the string is derived from the object, so publication is allowed.

+15
Jul 15 '11 at 13:25
source share

The reason they are different concepts is because, unlike the ascendant, covariance is not always allowed. It would be easy for the developers of a typical system to make IList<Cat> be considered β€œderived” from IList<Animal> , but then we encounter problems:

 IList<Cat> cats = new List<Cat>(); IList<Animal> animals = cats; animals.Add(new Dog()); //Uh oh! 

If it was allowed, now our cats list will contain Dog !

In contrast, the IEnumerable<T> interface does not have the ability to add elements, so this is perfectly true (in C # 4.0):

 IList<Cat> cats = new List<Cat>(); IEnumerable<Animal> animals = cats; //There no way to add things to an IEnumerable<Animal>, so here we are ok 
+6
Jul 15 2018-11-15T00:
source share
+1
Jul 15 '11 at 13:27
source share

From what I can collect, covariance eliminates the need for explicit downcasting after a previous upcast. Usually, if you raise an object, you can only access the methods and attributes of the base type, with covariance, it seems that you can indicate a downgrade by replacing smaller derived types with more derived types in a more derived class declaration.

0
Sep 04 '14 at 3:05
source share



All Articles