http://zh.wikipedia.org/wiki/%E5%8D%8F%E5%8F%98%E4%B8%8E%E9%80%86%E5%8F%98
协变与逆变是程序设计语言中的类型系统的一对概念。类型系统支持子类型。例如,如果Cat是Animal的子类型,那么Cat类型的表达式可用于任何出现Animal类型表达式的地方。 变型(variance)是指,如何根据其组成类型来确定更复杂的类型(如Cat列表对Animal列表,返回Cat的函数对返回Animal的函数,...,等等。)之间的子类型关系。依赖于类型构造器的变型性质,复杂类型的子类型性质可分为保持、逆转、与忽略。例如,在C Sharp中:
程序语言的设计者需要考虑针对数组、继承、泛型数据类型等的类型规则的“变型”。通过使得类型构造器是协变、逆变而不是“不变”,使得更多的程序可作为良好类型被接受。另一方面,程序员经常觉得逆变是不直观的;如果为避免运行时刻错误而精确跟踪变型将导致复杂的类型规则。为了保持类型系统简单,允许有用的编程,程序设计语言可把类型构造器处理为“不变”,即使它其实作为“变型”也是类型安全的;或者把类型构造器处理为协变,即使这会导致违背类型安全。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 |
using
System; namespace
TestCovarianceContravariance { public
class Shape { public
double Width { get ; set ; } public
double Height { get ; set ; } public
override string ToString() { return
String.Format( "Width: {0}, Height: {1}" , Width, Height); } } public
class Rectangle : Shape { } //如果泛型类型用out关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T。 //接口IIndex与类型T是协变的,并从一个只读索引器中返回这个类型 public
interface IIndex< out
T> { T this [ int
index] { get ; } int
Count { get ; } } public
class RectangleCollection : IIndex<Rectangle> { private
Rectangle[] data = new
Rectangle[3] { new
Rectangle {Height = 2, Width = 5}, new
Rectangle {Height = 3, Width = 7}, new
Rectangle {Height = 4.5, Width = 2.9} }; public
static RectangleCollection GetRectangles() { return
new RectangleCollection(); } public
Rectangle this [ int
index] { get { if
(index < 0 || index > data.Length) throw
new ArgumentOutOfRangeException( "index" ); return
data[index]; } } public
int Count { get
{ return
data.Length; } } } internal
class Program { private
static void Main( string [] args) { IIndex<Rectangle> rectangles = RectangleCollection.GetRectangles(); IIndex<Shape> shapes = rectangles; for
( int
i = 0; i < shapes.Count; i++) { Console.WriteLine(shapes[i]); } Console.WriteLine( "##########" ); IDisplay<Shape> shapeDisplay = new
ShapeDisplay(); IDisplay<Rectangle> rectangleDisplay = shapeDisplay; rectangleDisplay.Show(rectangles[0]); Console.WriteLine( "########## .net 框架中的示例 ###########" ); /* public interface IEnumerable<out T> : IEnumerable //协变 public delegate void Action<in T>( //逆变 T obj ) */ Action<Shape> b = (target) => { Console.WriteLine(target.GetType().Name); }; Action<Rectangle> d = b; //逆变:Shape是Rectangle的超类型,而Action<Rectangle>却是Action<Shape>的超类型 d( new
Rectangle()); b( new
Shape()); Console.ReadKey(); } } public
interface IDisplay< in
T> //该类型参数是逆变。即可以使用指定的类型或派生程度更低的类型。 { void
Show(T item); } public
class ShapeDisplay : IDisplay<Shape> { public
void Show(Shape s) { Console.WriteLine( "{0} Width: {1}, Height: {2}" , s.GetType().Name, s.Width, s.Height); } } } |
原文:http://www.cnblogs.com/wucg/p/3569170.html