方差有效性的确切规则有点模糊且不具体。我将列出使类型有效协变的规则,并将一些查询和个人注释附加到每个规则中。
一个类型是协变有效的,如果它是:
1) 指针类型,或非泛型类型。
指针和非泛型类型在 C# 中不是变体,但数组和非泛型委托除外。泛型类、结构和枚举是不变的。我在这里吗?
2) 数组类型 T[],其中 T 协变有效。
所以这意味着如果T
数组的元素类型T[]
是协变的(引用或数组元素类型),那么数组是协变的,如果元素类型是不变的(值类型),那么数组类型是不变的。数组在 C# 中不能逆变。我在这里吗?
3) 泛型类型参数类型,如果它没有被声明为逆变的。
我们通常说泛型类型是参数类型的变体,但参数类型本身就是变体。这是另一种说法吗?例如,泛型类型T<out D>
是协变的D
(因此是协变有效的),因此我们可以说类型参数D
是协变有效的。我对吗?
4) 构造的类、结构、枚举、接口或委托类型 X 可能协变有效。为了确定它是否是,我们以不同的方式检查每个类型参数,具体取决于相应的类型参数是否被声明为协变(out)、逆变(in)或不变(两者都不是)。(当然,类和结构的泛型类型参数永远不会被声明为“out”或“in”;它们将始终是不变的。)如果第 i 个类型参数被声明为协变,那么 Ti 必须协变有效。如果它被声明为逆变的,那么 Ti 必须是逆变有效的。如果它被声明为不变,那么 Ti 必须是不变有效的。
最后一条规则,从上到下,完全是模棱两可的。
我们是在谈论泛型类型在其所有输入/输出/不变类型参数上的差异吗?根据定义,泛型类型一次可以在一个类型参数上是协变/逆变/不变的。在这种情况下,要成为协变或不变的,同时对它的所有类型参数没有任何意义。那意味着什么?
向前进。为了确定泛型类型是否协变有效,我们检查它的类型参数(不是类型参数)。所以如果对应的类型参数是协变/逆变/不变的,那么类型参数分别是协变/逆变/不变有效...
我需要更深入地解释这条规则。
编辑:谢谢埃里克。非常感激!
我完全理解有效的协变/逆变/不变的含义。一个类型是协变有效的,如果它绝对不是逆变的,这意味着它可以是不变的。完全没问题!
对于第 4 条规则,您按照规则中定义的如何确定构造的泛型类型是否协变有效的过程。但是,如何确定声明为协变 (out) 的类型参数是否协变有效?
例如,在通用接口 I { ... }的封闭构造接口 I { }中,类型参数在通用接口声明中被声明为协变类型参数(out U)这一事实不应该意味着类型参数对象是协变的?我认为应该。因为这就是协变的定义。object
另外,第二条规则:
2) 数组类型 T[],其中 T 协变有效。
数组元素类型T
有效协变意味着什么?您的意思是元素类型是值类型(在这种情况下是不变的)还是引用类型(在这种情况下是协变的)?
因为投影T
→只有在引用类型T[]
时才变体。T