We already know the concepts and basic usage of array variance, interface, and delegate covariance. This article introduces another situation on variance, namely contra-variance.
Contra-variance is a scenario that converts generic types from large to small. Sometimes, for a generic delegate, we often need to reference and convert its type parameter t to facilitate the implementation of the composite or facade mode. Assume that D <t1> and D <t2> are two generic delegated D instances. t1 and t2 have an inheritance relationship, And t1 <t2, if D <t2> is implicitly converted to d <t1>, it is called D <> supports cotra-variance.
The generic types that support contra-variance can be expressed as x <in T> or x <t->, where X is an interface or delegate.
A simple example
This example shows how to use delegate processing to select the scenario where data is stored Based on the student object category. See the followingCode.
1: using system;
2: using system. Collections. Generic;
3: using system. LINQ;
4: using system. text;
5:
6: namespace demo
7 :{
8: Class Program
9 :{
10: static void main (string [] ARGs)
11 :{
12: primarystudent S1 = new primarystudent ();
13: juniorstudent S2 = new juniorstudent ();
14: seniorstudent S3 = new seniorstudent ();
15:
16: // define the generic save handler.
17: savefunc <student> savefunc = s => console. writeline (S. type );
18:
19: // set save delegates.
20: studentdatastore <student> datastore1 = new studentdatastore <student> ();
21: datastore1.savehandler = savefunc;
22: datastore1.save (S1 );
23:
24: studentdatastore <juniorstudent> datastore2 = new studentdatastore <juniorstudent> ();
25: // contra-variance.
26: datastore2.savehandler = savefunc;
27: datastore2.save (S2 );
28:
29: // no variance.
30: datastore2.save (juniorstudent) (student) S3 );
31 :}
32 :}
33:
34: Enum studenttype
35 :{
36: primary,
37: juniorhigh,
38: seniorhigh,
39: College,
40: Unknown
41 :}
42:
43: Delegate void savefunc <in T> (t student) where T: student;
44:
45: Class studentdatastore <t> where T: Student
46 :{
47: Public Virtual void save (t student)
48 :{
49: If (savehandler! = NULL)
50 :{
51: savehandler (student );
52 :}
53 :}
54: Public savefunc <t> savehandler {Get; set ;}
55 :}
56:
57: class student
58 :{
59: Public guid ID {Get; set ;}
60: Public string name {Get; set ;}
61: Public String controlnumber {Get; set ;}
62: Public Virtual studenttype type {Get; set ;}
63 :}
64:
65: Class primarystudent: Student
66 :{
67: Public override studenttype
68 :{
69: Get
70 :{
71: Return studenttype. Primary;
72 :}
73 :}
74 :}
75:
76: Class juniorstudent: Student
77 :{
78: Public override studenttype
79 :{
80: Get
81 :{
82: Return studenttype. juniorhigh;
83 :}
84 :}
85 :}
86:
87: Class seniorstudent: Student
88 :{
89: Public override studenttype
90 :{
91: Get
92 :{
93: Return studenttype. seniorhigh;
94 :}
95 :}
96 :}
97 :}
ProgramFirst, three student instances S1, S2, and S3 are created, and two studentdatastore instances are declared for different student types, and initialize the savehandler to the savefunc instance of a declared generic delegate. Note that the savefunc type is savefunc <student>. Since this type is declared as savefunc <in T>, contra-variance (47 rows) is supported ). The s1.savehandler type is savefunc <student>, which is the same as the right value type assigned. Therefore, the value assigned to s1.savezhandler is valid (21 rows ).
Let's take a look at the s2.savehandler assignment (26 rows ). The s2.savehandler type is savefunc <juniorstudent>, and the savefunc type is still not savefunc <student>. Here contra-variance is generated, converts a large savefunc <student> type to a small savefunc <juniorstudent> type.
Finally, let's take a look at S3. The S3 type is seniorstudent, while the datastore2.save () method requires a parameter of the juniorstudent type. Therefore, S3 must be forcibly referenced and converted to achieve the goal. Contra-variance is not found here.
Summary
Contra-variance is often used in generic delegation. It can solve some problems that need to be solved in common design patterns, and increase the width and value of generic applications to a greater extent. So far, our introduction to the variance feature has come to an end. If you have any further questions, please contact us. Next articleArticleWe will introduce the naming and optional parameters in C #4.0.
this article from the csdn blog, reprinted please indicate the source: http://blog.csdn.net/hustorochi/archive/2009/03/17/3998885.aspx