以下总结了我对C#中方差的理解。如果你能告诉我出错的原因,我会很感激,因为我读过关于 Exact rules for variance validity 的文章作者Eric Lippert,我无法理解其中的大部分内容。
方差是指一种类型转换(或者像Eric Lippert所说的那样)到另一种类型的转换可以保持赋值兼容性(协方差),或者反转它(逆变),或者既不保留它也不反转它(不变性) 。
那是;如果我是T中的协变变换,其中T是一组类型,那么对于T中的任何T1和T2类型,如果T1可分配给T2,则I<T1>
可分配给I<T2>
。如果我是逆变的,结果将被还原。如果我是不变的,则I<T1>
既不能分配给I<T2>
,也不能分配给相反的I<out T, in U>
。
现在,对于一个协变或逆变的类型意味着什么?方差不是类型投影的属性,而不是类型本身的属性。
泛型{{1}}在T上的协变性和U上的逆变是什么意思?
此外,逆变有效性如何逆转变异有效性的方向,协变有效性会逆转变异有效性的方向?
答案 0 :(得分:9)
现在,对于一个协变或逆变的类型意味着什么?变量不是类型投影的属性,而不是类型本身的属性吗?
是的,你是现实。好吧,你几乎现场。方差是类型相对于类型的给定关系的投影的属性。
考虑以下陈述:
从引用类型T
映射到类型IEnumerable<T>
的投影会保留赋值兼容性关系的方向,因此该投影是协变
从T
到IEnumerable<T>
的投影在T中是协变的。
IEnumerable<T>
在T
中是协变的。
IEnumerable<T>
是协变的。
我们说第四个;我们的意思是第一个。我们假设“IEnumerable<T>
是协变的”,从上下文可以清楚地看出投影是什么(从T
到IEnumerable<T>
)以及保留的关系是什么(赋值兼容性)。这样说更容易。
在你提到的那篇文章中,我起初比这更蹩脚;我使用“covariant”基本上意味着“可以在协变转换中以某种方式参与”。但是,“协同有效”等的定义是准确的。如果称它为“covariantly valid”使其难以理解,请将其称为其他内容:
如果类型X是指针,或非泛型,或者是具有Frobby元素类型的数组,或者是通用类型,其中每个“in”类型参数是Blobby,每个“out”类型,则称为类型X参数是Frobby,其他所有类型参数都是Frobby和Blobby。如果它是一个指针,非泛型或具有Blobby元素类型的数组,或者每个“in”类型参数都是Frobby,每个“out”类型参数都是Blobby,并且每个其他类型的论点是Frobby和Blobby。
在那里,我们根本没有使用“协变”或“逆变”这两个词,我们对Frobby和Blobby都有一个精确的定义。
通用类型
I<out T, in U>
在T
上的协变性和U
上的逆变是什么意思?
同样,这只是一个简短的表格。第一部分意味着对于任何固定的U
,从引用类型T
到I<T, U>
的投影是保留赋值兼容性方向的投影。如果X
的作业与Y
兼容且Z
为任何类型,则I<X, Z>
的作业与I<Y, Z>
兼容。
同样对于逆变部分,除了现在T
是固定的,投影反转关系的方向。
此外,“逆变有效性逆转变异有效性的方向”是什么意思?
我的意思是,如果您阅读协变有效性的规则并将其与逆变有效性的规则进行比较,您会注意到规则基本相同,只是一堆规则“向后转”。这就是我们称之为* contra * variance。
的原因我的博客上有十几篇关于差异的文章;如果这个主题让你感兴趣,你可能想从头开始阅读它们。