In-depth understanding of C # Covariance and Contravariance

Source: Internet
Author: User

Transfer from https://www.cnblogs.com/qixuejia/p/4383068.html

MSDN explains the following:

Covariant refers to the ability to use a more derived type than the original specified derived type.

"Contravariance" refers to the ability to use less derived types.

The explanation is correct, roughly the same, but not straightforward enough.

A straightforward understanding:

"Co-change", "Harmony Change", "very natural change"->string->object: covariant.

"Inverse", "inverse change", "abnormal changes"->object->string inversion.

Above is the individual understanding of covariance and contravariance, compared to remembering those derivation, type, original designation, larger, smaller words such as, personally think to be easy point.

Here's a joke:

Every day of one weeks should be read like this:

Monday = Busy day;
Tuesday = Death Day;
Wednesday = Not dead day;
Thursday = Dead Day;
Friday = Blessed day;
Saturday = Carefree Day;
Sunday = Injured Day

To demonstrate covariance and contravariance, and the difference between, create a console program Castudy, manually add two classes:

Because it's a demo, it's an empty class,

Just a little bit remember that dog inherits from Animal,

So dog becomes animal is the change of harmony (covariance), and if animal becomes dog it is abnormal change (inversion)

In the main function, enter:

Because dog inherits from animal, so animal aanimal = Adog; The Adog will be implicitly transformed into animal.

However, List<dog> does not inherit list<animal>, so the following prompt appears:

If you want to convert, you should use the following code:

list<animal> LstAnimal2 = Lstdogs.select (d = (Animal) d). ToList ();

You can see how complicated it is to turn a lstdogs into a lstanimal.

That's why Microsoft has added two new keywords: out,in, the following is their MSDN explanation:

The English of co-change is: "Covariant", the English of inversion is: "contravariant"

Why did Microsoft choose "Out" and "in" as attributes instead of them?

My personal understanding:

Because the English of covariance and contravariance is too complex, it does not reflect the difference between covariance and contravariance, but out and in is straightforward.

Out: Output (as a result), in: input (as parameter)

So if a generic parameter is marked as out, it is used for output and can only be returned as a result, and if a generic parameter is marked in, then it is used for input, that is, it can only be used as a parameter.

Currently the out and in keywords can only be used in interfaces and delegates, and the interfaces and delegates that Microsoft uses out and in tags are roughly as follows:

Let's take a look at the first ienumerable<t>.

As in the beginning, T is marked with out, so t represents the output, which is only returned as a result.

public static void Main ()

{

Dog Adog = new Dog ();

Animal aanimal = Adog;

list<dog> lstdogs = new list<dog> ();

list<animal> lstanimal = lstdogs;

list<animal> LstAnimal2 = Lstdogs.select (d = (Animal) d). ToList ();

ienumerable<dog> somedogs = new list<dog> ();

ienumerable<animal> someanimals = somedogs;

}

Because T can only do the result return, so T is not modified, the compiler can infer that the following statement is coerced into a valid, so

ienumerable<animal> someanimals = somedogs;

Can be checked by the compiler, the anti-compilation code is as follows:

Although the C # compiler's check is passed, IL does not know about covariance and contravariance, or it has to be a obediently cast.

Here I see this sentence:

ienumerable<animal> enumerable2 = (ienumerable<animal>) enumerable1;

Then is not can list<animal> LstAnimal3 = (list<animal>) lstdogs; It?

To answer this question you need to look back at the CLR via C # about generics and interfaces, and I won't explain.

The answer is no.

The above shows the covariance, and the next step is to demonstrate the inversion.

In order to demonstrate the inversion, it is necessary to find an in tag interface or a delegate, the simplest is:

In the main function, add:

action<animal> actionanimal = new Action<animal> (A + = {* Let animals be called */});

action<dog> Actiondog = Actionanimal;

Actiondog (Adog);

Obviously Actionanimal is let the animal call, because dog is animal, then since animal can call, dog certainly can also bark.

In keyword: contravariant, which represents input, is meant to be used only, not as a return value, so the C # compiler can infer from the in keyword that the generic type can only be used, so action<dog> actiondog = Actionanimal; Can be checked by the compiler.

Show the Out keyword again:

Add two classes:

public interface Imylist<out t>

{

T getelement ();

}

public class Mylist<t>: imylist<t>

{

Public T getelement ()

{

return default (T);

}

}

Because of the Out keyword, the following code can be compiled by

imylist<dog> mydogs = new mylist<dog> ();

imylist<animal> myanimals = mydogs;

Modify the above two classes to:

public interface Imylist<out t>

{

T getelement ();

void Changet (T t);

}

public class Mylist<t>: imylist<t>

{

Public T getelement ()

{

return default (T);

}

public void Changet (T t)

{

Change T

}

}

Compile:

Because T is modified by out, T can only be used as a parameter.

Also modify the two classes as follows:

public interface Imylist<in t>

{

T getelement ();

void Changet (T t);

}

public class Mylist<t>: imylist<t>

{

Public T getelement ()

{

return default (T);

}

public void Changet (T t)

{

Change T

}

}

This time use the In keyword.

Compile:

Because it is marked with the IN keyword, t can only be used, not as a return value.

The last modified code is:

public interface Imylist<in t>

{

void Changet (T t);

}

public class Mylist<t>: imylist<t>

{

public void Changet (T t)

{

Change T

}

}

The compilation was successful because in represents the inverse, so

imylist<animal> myanimals = new mylist<animal> ();

imylist<dog> mydogs = myanimals;

can be compiled successfully!.

In-depth understanding of C # Covariance and Contravariance

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.