In-depth understanding of C # Covariance and (reprint)

 

In-depth understanding of C # Covariance and

msdn explained as follows: 

"Covariance" refers to use compared to the original specified derived type, more derived type. 

"Inverter" refers able to use a smaller extent derived type. 

It is interpreted correctly, about right, but not enough straightforward. 

Straightforward to understand: 

"Covariant" -> "Harmony of Change" -> "natural change" -> string-> object: covariant. 

"Inverter" -> "inverse normal change" -> "abnormal changes" -> object-> string inverter. 

The above is a personal understanding of covariance and, compared to those derived in mind, type, specify the original, larger, smaller words and the like, personally think that is easier to spot. 

Here is a joke: 

Every day of the week should read like this:

Monday = busy day;
Tuesday = day to die;
Wednesday = dead day;
Thursday = by the death of day;
Friday = blessing to day;
Saturday = free and easy day;
Sunday = injury day

 

To demonstrate the difference between covariant and inverter as well, please create a console program CAStudy, manually add two classes: 

 

  

Because it is a demonstration, so are empty classes,

  

Just one thing to remember Dog inherits from Animal,

  

Animal Dog becomes so harmonious is a change (covariant), and if Animal Dog is turned into an abnormal change (inverter)

  

In the Main function input:

 

 

  

Because Dog inherits from Animal, so Animal aAnimal = aDog; aDog implicitly converted to Animal.

  

But List <Dog> does not inherit the List <Animal> so the following prompt:

  

 

  

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

  

List<Animal> lstAnimal2 = lstDogs.Select(d => (Animal)d).ToList();

  

You can see how a lstDogs become lstAnimal is a complex operation.

  

For this reason, so Microsoft added two keywords: Out, In, here are their msdn explanation:

 

 

 

 

Covariant English is: "covariant", the inverter is in English: "Contravariant"

  

Why Microsoft chose the "Out" and "In" as a characteristic and not them?

  

I understand:

  

Because Covariance and English too complicated and did not reflect the different covariant and inverter, but in and out is very straightforward.

  

out: output (as a result), in: input (as a parameter)

  

So if there is a generic parameter labeled OUT, represents the output of which is used, it can return only as a result, if there is a generic parameter labeled in, which represents the input is used, i.e. only It can be used as parameters.

  

Currently out and in keyword can only be used in interfaces and delegates, Microsoft and in the use of out-labeled interfaces and delegates as follows:

 

 

Dir a look IEnumerable <T>

 

 And just started saying, like, with out tag T, so T represents the output, that is, only to return 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;

}

 

Since T can only do the results returned, so T is not modified, the compiler can infer the following statement casts legitimate, so

IEnumerable<Animal> someAnimals = someDogs; 

Checking by the compiler, decompiled code is as follows: 

 

Although by the C # compiler checks, but il does not know covariance and, still have to obediently cast. 

Here I saw this sentence:

IEnumerable<Animal> enumerable2 = (IEnumerable<Animal>) enumerable1;

It is not to be List <Animal> lstAnimal3 = (List <Animal>) lstDogs; it? 

Want to answer this question needs to look back Clr via C # chapter on generics and interfaces, and I will not explain, 

The answer is no. 

Demonstrated above is covariant, then have to demonstrate at the inverter. 

To demonstrate the inverter, then they would find a mark in the interface or commissioned, the easiest is to: 

   

Add in the Main function: 

Action <Animal> actionAnimal = new Action <Animal> (a => {/ * Animals were called * /});

Action<Dog> actionDog = actionAnimal;

actionDog(aDog);

Obviously actionAnimal keep animals called because Dog is Animal, Animal since then can be called, Dog certainly can be called. 

In Keywords: inverter, represents an input, representing only be used, not as a return value, the C # compiler can infer keywords in accordance with this generic type can be used, so Action <Dog> actionDog = actionAnimal; check the compiler can. 

Out again demonstrates Keywords:

Add two categories:

public interface IMyList<out T>

{

    T GetElement();

}

 

public class MyList<T> : IMyList<T>

{

    public T GetElement()

    {

        return default(T);

    }

Because out keywords, so the following code can be compiled

IMyList<Dog> myDogs = new MyList<Dog>();

IMyList<Animal> myAnimals = myDogs;

 

The modification of the above two categories:

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 the modified T is out, so T only as a parameter.

 

Also modify two categories 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 in keywords.

Compile:

 

Because by in keyword tags, so T can only be used, not as a return value.

 

Finally, modify the code as follows:

public interface IMyList<in T>

{

    void ChangeT(T t);

}

 

public class MyList<T> : IMyList<T>

{

    public void ChangeT(T t)

    {

        //Change T

    }

}

 

Compile successful, because in behalf of the inverter, so

IMyList<Animal> myAnimals = new MyList<Animal>();

IMyList<Dog> myDogs = myAnimals;

 

You can compile successfully! .

Guess you like

Origin www.cnblogs.com/bedfly/p/11918970.html