Terms and concepts that have not been understood in those years: covariant, invert, unchanged, and unchanged terms

Source: Internet
Author: User

Terms and concepts that have not been understood in those years: covariant, invert, unchanged, and unchanged terms
Briefly describe what is covariance, inversion, and immutability

  • Covariance, such as: string-> object (Conversion from subclass to parent class)
  • Inverter, such as: object-> string (Conversion from parent class to subclass)
  • Immutable, based on the above two situations, immutable. Perform the following analysis.
Variability of generic delegation

First, use the generic delegation Func AND Action defined by the framework as an example (for details, see the timestamp)

Covariant: (string-> object)

Func <string> func1 = () => "farm Code life"; Func <object> func2 = func1;

Inverter: (object-> string)

Action<object> func3 = t => { };Action<string> func4 = func3;

The above Code has no problems.

Next, let's try to define the delegate by ourselves:

I am X, it seems that no one is here. Why can't custom DelegationCovariantAnd.

Let's take a look at the differences between the system-defined Func and our custom one:

public delegate TResult Func<out TResult>();

With an out, what's the Ghost:

  • Out: For generic type parameters, the out keyword specifies that this type parameter is covariant. You can use the out keyword in generic interfaces and delegation. (Source)
  • In: For generic type parameters, the in keyword specifies that this type parameter is inverter. You can use the in keyword in generic interfaces and delegation. (Source)

Then we can modify the custom delegate:

Perfect!

So what if we want to achieve the inverter:

Direct inversion is not feasible. We need to modify the generic parameters:

We found that the entire delegate parameter has changed. The original return value is changed to the input parameter.

Conclusion:

  • In-> input parameter-> invert (transformation from parent class to subclass [such as object-> string])
  • Out-> return value-> covariant (transformation from subclass to parent class [such as string-> object])

 

Suppose: how to change the out parameters that exist in both in and out parameters:

delegate Tout MyFunc<in Tin, out Tout>(Tin obj);
MyFunc <object, string> str1 = t => "farm Code life"; MyFunc <string, string> str2 = str1; // The first generic inverter (object-> string) MyFunc <object, object> str3 = str1; // The second generic covariant (string-> object) myFunc <string, object> str4 = str1; // The first generic inverter and the second generic covariant

All of the above are correct.

Then let's take a look.After compilationC # code:

Conclusion:

  • The so-called inverter is only forced type conversion after compilation.

The above code can also be written directly as follows:

// Delegate ToutMyFunc<In Tin, out Tout> (Tin obj); MyFunc <string, string> str5 = t => "farm Code life"; MyFunc <object, object> str6 = t => "farm Code life"; MyFunc <string, object> str7 = t => "farm Code life ";
Variability of generic Interfaces

Next, let's look at the default framework interface:

Covariant:(Subclass-> parent class)

IEnumerable<string> list = new List<string>();IEnumerable<object> list2 = list;

Inverter:(Parent class> subclass)

IComparable<object> list3 = null;IComparable<string> list4 = list3;

Next, we will try custom generic interfaces:

First, define the test Type and interface:

// Public class People {} // Teacher (inheriting People [persons]) public class Teacher: people {}// sports public interface IMotion <T >{} // running public class Run <T>: IMotion <T> {}

Then we test the covariance:

Similarly, we need to define the interface IMotion <T> as interface IMotion <out T>

// Sports public interface IMotion <out T> {}
IMotion<Teacher> x = new Run<Teacher>();IMotion<People> y = x;

If we want to test the inverter, we need to define interface IMotion <T> as interface IMotion <in T>

// Sports public interface IMotion <in T> {}
IMotion<People> x2 = new Run<People>();IMotion<Teacher> y2 = x2;

The inverter of the generic interface is also forced after compilation:

Of course, we can also directly write it:

IMotion<Teacher> y3 = new Run<People>();
Immutability

From the above we know that the code of the inverter will be forcibly converted after compilation.Hypothesis: Can we manually force the conversion without going out or in? :

// Public class People {} // Teacher (inheriting People [persons]) public class Teacher: people {}// sports public interface IMotion <T >{} // running public class Run <T>: IMotion <T> {}
// Covariant IMotion <Teacher> x = new Run <Teacher> (); IMotion <People> y = (IMotion <People>) x; // invert IMotion <People> x2 = new Run <People> (); IMotion <Teacher> y2 = (IMotion <Teacher>) x2; IMotion <Teacher> y3 = (IMotion <Teacher>) new Run <People> ();

I found that the compilation was successful, and there was no problem! Can it also be changed at the same time ??NoIs it really a genius? Run the following command:

It seems that I am still too simple. If it is so easy to get around, why should Microsoft get out and in keywords.

For the same generic parameter, what should we do? The answer is not feasible. This will lead to the third case, which neither can be changed together nor can be inverter. This is called immutability.

For example (we define two methods in IMotion ):

// Motion public interface IMotion <T> {T Show (); void Match (T t );}

As we tested above, direct forced conversion of code cannot achieve covariant and invert. So we can only implement it through out and in. What if we add the out or in attribute in the generic parameter? :

We found that both out and in cannot be used. When an out clause is used, a method with the input parameter generic void Match (T t) is provided. When in is used, there is a method that returns the parameter T Show. Now it appearsYes. The spear is sharper.,Or is shield harder?.

The final result is: none can be used, and neither can be changed or changed. This isUnchanged body.

TIPS:

APIS such as IEnumerable <T>, IComparable <T>, and IQueryable <T> earlier than C #4.0 do not support variability. Because the out and in keywords are not added to the generic interface defined before 4.0, you can switch the version if you are interested.

Extended thinking

Why can't in [input parameters] be converted to an inverter?The analysis is as follows:

// Public class People {} // Teacher (inheriting People [persons]) public class Teacher: People {// Salary public decimal Salary {get; set ;}} // sports public interface IMotion <in T> {void Match (T t);} // running public class Run <T>: IMotion <T> {public void Match (T t) {// assume there are many logics in the middle .....}}

Why do out [return values] only support covariant?The analysis is as follows:

// Public class People {} // Teacher (inheriting People [persons]) public class Teacher: People {// Salary public decimal Salary {get; set ;}} // sports public interface IMotion <out T> {T Show (); // void Match (T t);} // running public class Run <T>: IMotion <T> {public T Show () {return default (T);} // public void Match (T t) // {// assume there are many logics in the middle ..... //}}

There are two key points:

  • The incoming parameter (in) is used to treat the parameter as the parent class.Obviously, it can be used as an inverter (the sub-class is treated as a parent class using the [Lee's replacement principle]), but the parent class cannot be used as a subclass (for example: subclass has methods or attributes that the parent class does not have ).
  • Return Value (out) the type of returned value is received by the parent class.Obviously, it can be changed (the parent class can receive all sub-classes), but it cannot be used to receive parent class data (such: objects represented by the parent class cannot be forcibly transferred to the subclass [string str = (string) objcet]).

... The more you think about it, the more dizzy you are. Do it yourself.

If you really want a big head, think of it as a turtle's ass (turtles \ rules), knowing that it is a security restriction made by C!

Summary

Variability of generic interfaces and delegation:

  • Covariant-> more harmonious normal changes-> sub-class to parent class [for example, string to object]-> The out ID must be included [return value]
  • Inverter-> changes against the day-> parent rotor class [such as object to string]-> must have an in MARK [input parameters] (the father becomes a son, the more active the younger, isn't it against the day ?)
  • The so-called inverter will force type conversion in the compiled C # code.
  • Example:
    • IEnumerable <string> list = new List <string> ();
      IEnumerable <object> list2 = list; // covariant
      IEnumerable <object> list2 = new List <string> (); // (this can also be written directly)

    • IComparable <object> list3 = null;
      IComparable <string> list4 = list3; // After the inverter is compiled [ IComparable <string> list4 = (IComparable <string>) List3;]

Note:

  • The variability of type parameters of classes is not supported.
  • Only generic interfaces and generic delegation can have variable type parameters (out and in)
  • Variability only supports reference conversion. (Cannot be used for value type)
  • The type parameter uses out or ref to disable variability.

 

Now, we are here today. There is no profound technical knowledge, mainly to understand terms and concepts such as covariant, inverter, and unchanged body.

This article has been synchronized to the index directory: C # basic knowledge Consolidation

 

Recommended articles of the same type:

Http://www.cnblogs.com/haoyifei/p/5760959.html

Http://www.cnblogs.com/LoveJenny/archive/2012/03/13/2392747.html

Http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html

 

Related Article

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.