Covarience And ContraVariance
19144 ワード
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4
5 namespace CovarientAndContraVarient
6 {
7 class Program
8 {
9 static object GetObject() { return null; }
10 static void SetObject(object obj) { }
11
12 static string GetString() { return ""; }
13 static void SetString(string str) { }
14
15 static void Main(string[] args)
16 {
17 Func<object> getString = GetString;
18
19 Action<string> setString = SetObject;
20
21 Func<string> getString1 = GetString;
22
23 //1. Delegate variable implicitly cast is not valid until .net 4.0
24 Func<object> setString2 = getString1;
25
26 //Assignment compatibility,
27 IEnumerable<String> test = new List<string>();
28
29 //covariance OUT == > Covariance
30 IEnumerable<object> test1 = new List<string>();
31
32 //Assignment compatibility
33 Action<Object> objAction = StaticMethod;
34
35 //ContraConvariance , IN === > ContraConvariance
36 Action<String> stringAction = StaticMethod;
37
38 //2. Array Covariance, support in C# 1.0
39 object[] objArray = new String[] { "a", "b", "c" };
40
41 //Covariance in array is not safe, below code will throw exception
42 objArray[0] = 5;
43
44 //3. Co/contra- Variance don't support value type, below code is invalid
45 //IEnumerable<object> objects = new List<int>();
46
47 //you can use an interface instance that has methods with more
48 //derived return types than originally specified (covariance--OUT)
49 //or that has methods with less derived parameter types (contravariance--IN).
50
51 //Contravariance
52 IMyTest<FileStream> myTestInstance = new MyTestClass1<Stream>();
53
54 IMyTest<Stream> myTest = new MyTestClass1<Stream>();
55
56 //covariance
57 IMyTest1<object> myTest1Instance = new MyTestClass2<string>();
58
59 IMyTest<FileStream> myTestInstance1 = myTest;
60
61 //Below Code, you will think it is a little strange, but absolutely it works well!!!!!!!!!
62 //4. You can mark a generic type parameter as covariant if it is used only as a method return
63 //type and is not used as a type of formal method parameters.
64 //5. And vice versa, you can mark a type as contravariant if it is used only as a type of
65 //formal method parameters and not used as a method return type.
66 IMyFirstTestClass<object, string> testClass = null;
67 IMyFirstTestClass<string, object> testClass1 = testClass;
68 }
69
70 public static void StaticMethod(object o)
71 {
72 }
73 }
74
75 public interface IMyFirstTestClass<in T1, out T2>
76 {
77 T2 DoSomething(T1 para);
78 }
79
80
81
82 //6. Variant type only can declared in interfaces and delegates only!!!!!!!
83 //public class MyTestClass<in T>
84 //{
85
86 //}
87
88 //Contravariance
89 public interface IMyTest<in T>
90 {
91 void PrintTest(T param);
92 }
93
94 //7. Below code, T is invariance, if you want to it be Contravariance, you must declare it explicitly.
95 //Same as covariance
96 public interface IMyTestExtend<T> : IMyTest<T>
97 {
98 }
99
100 public class MyTestClass1<T> : IMyTest<T>
101 {
102 public void PrintTest(T para)
103 {
104 Console.WriteLine("This is " + typeof(T) + " PrintTest Method!");
105 }
106 }
107
108 //Covariance
109 public interface IMyTest1<out T>
110 {
111 T PrintTest();
112 }
113
114 public class MyTestClass2<T> : IMyTest1<T>
115 {
116 public T PrintTest()
117 {
118 Console.WriteLine("This is " + typeof(T) + " PrintTest Method!");
119 return default(T);
120 }
121 }
122
123 public delegate void MyHander<in T>(T para);
124
125 //Below method declaration is invalid, because 'in' is contravariance, it only can be in paramter type
126 //public delegate T MyHander1<in T>(T para);
127
128 public delegate T MyHandler2<out T>(object para);
129
130 //Below method declaration is invalid, because 'out' is covariance, it only can be in returned type
131 //public delegate void MyHandler2<out T>(T para);
132
133 }
FYI: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx