1

以下总结了我对 C# 中方差的理解。如果您能告诉我我做错了什么,我将不胜感激,因为我阅读了Eric Lippert 撰写的关于方差有效性的精确规则的文章,但我无法理解其中的大部分内容。

方差是一种类型到另一种类型的转换(或 Eric Lippert 所说的投影)可以保持赋值兼容性(协变)或反转它(逆变),或者既不保持也不反转它(不变性)的想法。那是; 如果 I 是 T 中的协变变换,其中 T 是一组类型,则对于 T 中的任何 T1 和 T2 类型,如果 T1 可分配给 T2,则可I<T1>分配给I<T2>。如果我是逆变的,结果将被还原。如果我是不变的,那么既不I<T1>是可分配的,I<T2>也不是相反的。

现在,类型协变或逆变意味着什么?方差不是类型投影的属性,而不是类型本身的属性。

I<out T, in U>泛型类型在 T 上协变而在 U 上逆变是什么意思?

另外,逆变效度反转变体效度的方向和协变效度反转变体效度的方向是什么意思?

4

1 回答 1

9

现在,类型协变或逆变意味着什么?方差不是类型投影的属性而不是类型本身的属性吗?

是的,你是正确的。好吧,你几乎是正确的。方差是关于类型上给定关系的类型投影的属性。

考虑这些陈述:

  • 从引用类型映射T到类型的投影IEnumerable<T>保留了分配兼容性关系的方向,因此该投影是协变的。

  • T从to的投影IEnumerable<T>在 T 中是协变的。

  • IEnumerable<T>在 中是协变的T

  • IEnumerable<T>是协变的。

我们说第四个;我们的意思是第一个。我们假设通过“IEnumerable<T>是协变的”,从上下文中可以清楚地看出投影是什么(从TIEnumerable<T>)以及保留的关系是什么(分配兼容性)。那样说起来更容易。

在你提到的文章中,我一开始比这更草率;我使用“协变”基本上是指“可以以某种方式参与协变转换”。但是,“协变有效”等的定义是精确的。如果称其为“协变有效”让人难以理解,请称其为其他名称:

如果类型 X 是指针、非泛型、具有 Frobby 元素类型的数组或泛型类型,其中每个“in”类型参数是 Blobby,每个“out”类型参数都是 Frobby,则类型 X 称为 Frobby 类型,并且所有其他类型参数都是 Frobby 和 Blobby。如果它是一个指针,或者非泛型,或者具有 Blobby 元素类型的数组,或者一个泛型类型,其中每个“in”类型参数都是 Frobby,每个“out”类型参数都是 Blobby,那么它就被称为 Blobby,并且每个其他类型参数是 Frobby 和 Blobby。

在那里,我们根本没有使用“协变”或“逆变”这两个词,而且我们对 Frobby 和 Blobby 都有一个精确的定义。

I<out T, in U>泛型类型是协变的T和逆变的是什么意思U

同样,这只是一个简短的形式。第一部分意味着对于任何 fixed U,从引用类型TI<T, U>的投影是一个保留分配兼容性方向的投影。如果X赋值兼容Y并且Z是任何类型,那么I<X, Z>赋值兼容I<Y, Z>

同样对于逆变部分,除了现在T是固定的,并且投影反转了关系的方向。

另外,“逆变有效性反转了变量有效性的方向”是什么意思?

我的意思是,如果您阅读协变有效性规则并将它们与逆变有效性规则进行比较,您会注意到规则基本相同,只是一堆规则“倒退”了。这就是为什么我们称它为* contra *variance。

我的博客上有十几篇关于方差的文章;如果您对这个主题感兴趣,您可能想从头开始阅读它们。

于 2013-04-26T04:31:25.937 回答