[C #] talking about covariant and Inverter
What are the terms of the covariant and inverter covariant and the inverter? The former refers to a type that can be derived to a lower degree (not specific) than the original specified derivative type, the latter refers to a type that can be derived more (more specific) than the original specified derivative type. Generic Type parameters support covariant and inverter, providing greater flexibility in allocating and using generic types. At the beginning, I could not tell whether the changes were covariant or inverter, because the MSDN explanation was more rigorous and less readable. In fact, it is quite easy to understand these two concepts from the literal perspective of Chinese: "covariant" means "coordinated transformation" and "inverter" means "reverse transformation ". Why is it possible to use a type that is less (not specific) than the original specified derivative type, however, "the type that can be used to derive a greater degree (more specific) than the original specified derivative type" is inverse. Let's look at the two lines of code: object o = ""; string s = (string) o; the string type can be implicitly converted to the object type, that is, the derived class to the base class, because the conversion from any type to the base class is of type security, therefore, this transformation is coordinated. The object type to the string type, that is, the base class to the derived class, can only be explicitly converted, because the actual type of object o is not necessarily string, forced conversion is not type-safe, therefore, this transformation is considered inverse. Let's look at the common scenarios of covariant and inverter: IEnumerable <object> o = new List <string> (); // covariant Action <string> s = new Action <object> (arg) => {...}); // The Generic parameters of the inverter are coordinated and reversed. From the definition, we can see that both the covariant and the inverter are generic parameters. in. NET Framework 4, Variant type parameters are limited to generic interfaces and generic Delegate types. Why interfaces and delegation? First, let's look at the Declaration of IEnumerable <T> and Action <T>:
public interface IEnumerable<out T> : IEnumerable{ new IEnumerator<T> GetEnumerator();}
Public delegate void Action <in T> (T obj); The out keyword in IEnumerable provides covariant capabilities for generic parameters, the in keyword in Action provides the ability to invert generic parameters. Here, the out and in are relative to who's in and out? It is not relative to the interface and delegate, but to the method body! See their implementation:
class MyEnumerable<T> : IEnumerable<T>{ public IEnumerator<T> GetEnumerator() { yield return default(T); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }}Action<string> myAction = new Action<object>( (o) => { Console.WriteLine(o.ToString()); });
Does this show how generic parameters are imported and output? What is the relationship between interfaces and delegation and methods? What is the relationship between them? The following is my understanding: the interface type defines a set of method signatures, the delegate type defines a method structure (method signature division method name ). Both the interface instance and the delegate instance contain a set of method entries. To sum up, the objects used by the covariant and inverter are generic parameters in the method body. Why are the types allowed to be converted from the covariant to the inverter? Once the type conversion is involved, you must consider the type security issue. The reason why covariant and inverter work properly is that all types involved here are type-Safe! Look back at the first four lines of code: 1 object o1 = ""; // type security 2 string s1 = (string) o1; // non-type security 3 IEnumerable <object> o2 = new List <string> (); // covariant 4 Action <string> s2 = new Action <object> (arg) => {...}); // It is clear that the object from the second line to the string is non-safe. Why is the object from the fourth line to the string safe? Based on the example of the previous method body, let's look at this Code:
1 Action<List<int>> myAction = new Action<IList<int>>(2 (list) =>3 {4 Console.WriteLine(list.Count);5 });6 myAction(new List<int> {1, 2, 3});
The first line seems to be converting IList to List, but it is actually like this: the real parameter passed in the sixth row is a List and enters the method body. The List is converted to IList, then the Count attribute of IList is used. Therefore, when passing parameters, the conversion from the derived class to the base class actually occurs, that is, the type is safe. The covariant from List <string> to IEnumerable <object> is similar:
1 IEnumerable<Delegate> myEnumerable = new List<Action> 2 { 3 new Action(()=>Console.WriteLine(1)), 4 new Action(()=>Console.WriteLine(2)), 5 new Action(()=>Console.WriteLine(3)), 6 }; 7 foreach (Delegate dlgt in myEnumerable) 8 { 9 dlgt.DynamicInvoke();10 }
The real parameter is three actions, and the Delegate DynamicInvoke method is called, which is completely type-safe conversion.