C #4.0 new features-"covariant" and "invert" and the programming ideas behind it)

Source: Internet
Author: User

Introduction: Author: Jiang Jinnan, network name: artech. The MVP of the solution architecture and interconnection system is the most influential developer of Microsoft. In 《C #4.0 Implementation of the new "default parameter"We reveal the essence of "default parameters". Now let's talk about another important new feature in C #4.0: covariance and contravariance ). We are certainly not unfamiliar with covariant and inverter, But I believe many people cannot clearly tell the difference between them. I hope that this article will give readers a deeper understanding of covariant and inverter. The content of this article is as follows:

 

I. Two Concepts: strong type and weak type

 

For the convenience of subsequent descriptions, I now define two concepts: strong type and weak type. In this article, strong and weak types refer to two classes with direct or indirect inheritance relationships. If a class is a direct or indirect base class of another class, it is a weak type, and the direct or indirect subclass is a strong type. The Foo and bar classes used in subsequent introductions are defined here. Bar inherits from Foo. Foo is a weak type, while bar is a strong type.

 

1: Public class foo

2 :{

3: // others members...

4 :}

5: public class bar: foo

6 :{

7: // others members...

8 :}

 

With the concept of strong and weak types, we can define co-Variation and inversion in this way: if the type of tbar is based on the type of strong bar (for example, the Type parameter is bar's generic type, or the parameter/return value type is bar delegate), while the tfoo type is based on the foo type of the weak type, the covariant is to assign the tbar type instance to the variable of the tfoo type, the inverter assigns a tfoo-type instance to a variable of the tbar type.

Ii. Use of coordination and inverter in Delegation

 

The coordination and inverter are mainly reflected in two aspects: interface and delegation. First, let's take a look at how to use the coordination and inverter in the delegation. Now we have defined a generic delegate function <t> that represents a function without parameters. The type parameter is the type of the function return value. An out keyword is added before the generic parameter to indicate that T is a covariant. During use, the forced-type delegated fucntion <bar> instance can be assigned a value to the weak-type delegated fucntion <Foo> variable.

 

1: Public Delegate t function <out T> ();

2: Class Program

3 :{

4: static void main ()

5 :{

6: function <bar> funcbar = new function <bar> (getinstance );

7: function <Foo> funcfoo = funcbar;

8: Foo = funcfoo ();

9 :}

10: static bar getinstance ()

11 :{

12: return new bar ();

13 :}

14 :}

 

Next we will introduce how to use inverter delegation. The following defines a generic delegate named operate to accept a parameter with a generic parameter type. The in keyword is added before defining generic parameters, indicating that t is an inverter-based variant. Because of the inverter, we can assign the weak type-based delegated operate <Foo> instance to the forced type-based delegated operate <bar> variable.

 

1: Public Delegate void operate <in T> (T instance );

2: Class Program

3 :{

4: static void main ()

5 :{

6: operate <Foo> opfoo = new operate <Foo> (dosomething );

7: operate <bar> opbar = opfoo;

8: opbar (new bar ());

9 :}

10: static void dosomething (Foo)

11 :{

12: // others...

13 :}

14 :}

 

Iii. Use of covariant and inverter in Interfaces

 

Next we will also use a simple example to illustrate how to use the covariant and inverter in the interface. The following defines an igroup <out T> set type inherited from the ienumerable <t> interface. Like above, the out keyword before the generic parameter t indicates that this is a covariant. Since it is a covariant, we can assign a forced type-based delegated igroup <bar> instance to the weak type-based delegated igroup <Foo> variable.

 

1: Public interface igroup <out T>: ienumerable <t>

2 :{}

3: Public class group <t>: List <t>, igroup <t>

4 :{}

5: Public Delegate void operate <in T> (T instance );

6: Class Program

7 :{

8: static void main ()

9 :{

10: igroup <bar> groupofbar = new group <bar> ();

11: igroup <Foo> groupoffoo = groupofbar;

12: // others...

13 :}

14 :}

 

The following is an example of an inverter interface. First, an ipaintable interface is defined, which defines a read/write color attribute, that is, the object that implements this interface has its own color and can change the color. The type car implements this interface. The interface ibrush <in T> defines a brush. The generic type must implement the ipaintable interface. The in keyword indicates that this is an inverter. The method paint is used to paint the specified object into the corresponding color, indicating that the type of the object to be painted is generic parameter type. Brush <t> implements this interface. Because ibrush <in T> is defined as an inverter, we can assign a value to the weak type-based delegated ibrush <car> variable.

 

1: Public interface ipaintable

2 :{

3: color {Get; set ;}

4 :}

5: public class car: ipaintable

6 :{

7: Public color {Get; set ;}

8 :}

9:

10: public interface ibrush <in T> where T: ipaintable

11 :{

12: void paint (T objecttopaint, color );

13 :}

14: public class brush <t>: ibrush <t> where T: ipaintable

15 :{

16: Public void paint (T objecttopaint, color)

17 :{

18: objecttopaint. Color = color;

19 :}

20 :}

21:

22: Class Program

23 :{

24: static void main ()

25 :{

26: ibrush <ipaintable> brush = new brush <ipaintable> ();

27: ibrush <car> carbrush = brush;

28: Car car = new car ();

29: carbrush. Paint (CAR, color. Red );

30: console. writeline (car. color. Name );

31 :}

32 :}

 

Iv. view the essence of coordination and inverter from func <t, tresult>

 

Next, let's talk about the essential differences between covariant and inverter. Here we use a very familiar entrusted func <t, tresult> as an example. The definition of this delegate is given below. We can see that the two generic parameters defined by func <t, tresult> belong to the inverter and collaborative change respectively. Specifically, the input parameter type is invert, And the return value type is covariant.

 

1: Public Delegate tresult func <in T, out tresult> (T Arg );

 

Repeat the following sentence: "The input parameter type is inverter, And the return value type is covariant ". Then, you can think about why the in keyword is used for inverter, And the out keyword is used for covariant. These two are not accidental. In fact, we can match the covariant/inverter with the output/input.

 

From another perspective, we can understand the coordination and inverter. We know that an interface represents a contract. When an interface is implemented by a type, it is equivalent to signing this contract, so it must be all the members of the Implementation interface. In fact, type inheritance also belongs to a contractual relationship. The basic class defines the contract, and the subclass "signs" the contract. For a type system, the interface implementation and type inheritance are essentially the same. The contract type is weak, and the contract type is strong.

 

Apply the contract idea to the delegate. The delegate actually defines the signature of a method (parameter list and return value). The type of parameters and return values is contract, the key now is who will fulfill the contract. All parameters are input from outside, so the contract operator based on parameters comes from outside, that is, the type of the variable to be assigned, so the type of the variable to be assigned is strongly. For the agent itself, a parameter is an input, that is, an inverter represented by the In keyword.

 

For the return value of the Delegate, this is for external services and a commitment from the entrusting itself to the outside world. Therefore, it is the fulfillment of the contract itself, so it should be a strong type. Correspondingly, for the proxy itself, the return value is an output, that is, a covariant defined by the out keyword.

 

Also, for this reason, for a delegate, you cannot define the parameter type as a covariant or convert the return type. The following two variant definitions cannot be compiled.

 

1: Delegate tresult fucntion <out t, tresult> (T Arg );

 

2: Delegate tresult fucntion <t, in tresult> (T Arg );

 

Speaking of this, I want to ask a question. Since the input represents an inverter and the output represents a covariant, should the output parameter of the delegate be defined as a covariant? Also, the output parameters both output and output here (after all, you need to specify an object of the corresponding type when calling ). For this reason, the type of the output parameter cannot be defined as a covariant or an inverter. Therefore, the definitions of the following two variants cannot be compiled.

 

1: Delegate void action <in T> (out t Arg );

 

2: Delegate void action <out T> (out t Arg );

 

Although the Agreement and input/output relations mentioned above are also applicable to API-based coordination and inverter. You can analyze the igroup <Foo> and ibrush <in T> defined in the above section.

V. inverter achieves reuse of "algorithms"

 

In fact, the programming ideology embodied by the relationship covariant and inverter is also a type of concept that I highly recommend: The covariant represents the inheritance, while the inverter represents the polymorphism. In fact, this is essentially the same as the contract relationship analyzed above.

 

For inverter, let me try again: the programming ideas behind the inverter reflect the reuse of algorithms-we have defined a set of operations for the Base class, it can be automatically applied to all subclass objects.

Link: http://www.cnblogs.com/artech/archive/2011/01/13/1934914.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.