方差有效性的精确规则有点模糊,不太具体。我将列出使类型有效的规则,并在每个规则上附加一些查询和个人注释。
一个类型是有效的,如果它是:
1)指针类型,或非泛型类型。
指针和非泛型类型在C#中不变体,但数组和非泛型委托除外.泛型类、结构和枚举是不变的。我就在这儿吗?
2)数组类型T[],其中T是有效的。
这意味着,如果数组的元素类型T是协变量(引用或数组元素类型),那么数组是协变量的,如果元素类型是不变的(值类型),那么数组类型是不变的。数组在C#中不能是反变体。我就在这儿吗?
( 3)泛型类型参数类型(如果未声明为反变体)。
我们通常说泛型类型在参数类型上是可变的,但是参数类型本身是可变的。这是又一种简短的说法吗?例如,泛型类型T<out D>在D上是协变的(因此是有效的),因此我们可以说类型参数D是协变量有效的。我说的对吗?
4)构造的类、结构、枚举、接口或委托类型X可能是共同有效的。为了确定是否是,我们根据对应的类型参数是否声明为协变量(out)、反变量(in)或不变量(都不声明),对每个类型参数进行不同的检查。(当然,类和结构的泛型类型参数永远不会被声明为“out”或“in”;它们总是不变的。)如果ith类型参数声明为协变量,则Ti必须是有效的协变量。如果它被宣布为反变体,则Ti必须是有效的。如果它被声明为不变量,则Ti必须是有效不变的。
的最后一条规则,自上而下,都是非常模糊的。
我们讨论的是泛型类型对其所有输入/输出/不变类型参数的方差吗?根据定义,泛型类型可以是一次在一种类型参数上的协变/反变/不变量。在这种情况下,要成为协变量或不变量,它的类型参数一次就不具有任何意义。这可能意味着什么?
向前看。为了确定泛型类型是否具有协变量有效性,我们将检查它的类型参数(非类型参数)。因此,如果对应的类型参数是协变/逆变/不变量,则类型参数分别是有效的协变量/逆变/不变的。
我需要更深入地解释这个规则。
编辑:谢谢,埃里克。非常感谢!
我完全理解什么是有效的,共变的/反差的/不变的。一个类型是有效的,如果它绝对不是反变体,这意味着它可以是不变的。完全没问题!
对于第4条规则,按照规则中的定义,遵循如何确定构造的泛型类型是否是有效的过程。但是,如何确定声明为协变量(out)的类型参数是否具有协变量的有效性?
例如,在泛型接口I{. }的封闭构造接口I{}中,不应该将类型参数object声明为协变类型参数(Out),这意味着类型参数对象是协变的吗?我觉得应该。因为这就是协变的定义。
此外,第二条规则:
2)数组类型T[],其中T是有效的。
数组元素类型T 是有效的是什么意思?您的意思是元素类型是值类型(在本例中是不变的)还是引用类型(在本例中是协变的)?
因为投影T→T[]只有当T是引用类型时才是变体。
发布于 2013-04-27 00:31:00
你说得对,最后一条规则是最难理解的,但我向你保证,它并非模棱两可。
一两个例子会有帮助。请考虑以下类型声明:
interface I<in T, out U, V> { ... }此类型是否具有协变量有效性?
I<string, object, int> { }让我们来看看我们的定义。
为了确定是否是,我们根据对应的类型参数是否声明为协变量(out)、反变量(in)或不变量(都不声明),对每个类型参数进行不同的检查。
好的,所以类型参数是string、object和int。相应的参数分别为in T、out U和V。
如果ith类型参数声明为协变量(
out),则Ti必须是有效的协变量。
第二个类型的参数是out U,所以object必须是有效的。它是。
如果它被宣布为反变异体(
in),则Ti必须是有效的。
第一个被声明为in T,因此string必须是有效的。它是。
如果它被声明为不变量,则Ti必须是有效不变的。
第三种V是不变量的,所以int必须是不变的,所以它必须是有效的,既可以是对比的,也可以是共变的。它是。
我们通过了所有三个检查;类型I<string, object, int>是有效的。
好吧,那个很简单。
现在让我们来看看一个更难的问题。
interface IEnumerable<out W> { ... }
interface I<in T, out U, V>
{
IEnumerable<T> M();
}IEnumerable<T> is I是一种类型。IEnumerable<T>在I中的使用是否有效?
让我们来看看我们的定义。类型参数T对应于类型参数out W。注意,T是I的类型参数和IEnumerable的类型参数。
如果ith类型参数(
W)声明为协变量(out),则Ti (T)必须是有效的协变量。
好的,如果IEnumerable<T>在I中是有效的,那么T必须是有效的。是吗?不是的。T被宣布为in T。声明为in的类型参数从不会以协变方式有效。因此,在IEnumerable<T>中使用的I类型是无效的,因为违反了“必须”条件。
再一次,就像我在回答你之前的问题时说的,如果“有效共变”和“有效对比”会给你带来悲伤,那就给他们起不同的名字吧。它们是定义良好的正式属性;如果它使您更容易理解,您可以将它们称为任意类型的属性。
发布于 2013-04-26 23:53:40
不,你的注解搞砸了。
这篇文章真的很难理解,部分原因是“有效的协变量”与协方差毫无关系。Eric确实指出了这一点,但它意味着对于每句话,你都必须“不去思考”自然的含义,然后用这些奇怪的定义来思考“有效共变”、“有效对比”和“有效不变”。
我强烈建议您阅读Liskov替换原则,然后考虑可替换性。从LSP的角度来看,协方差、反方差和不变性有着非常简单的定义。
然后,您可能会注意到,编译时的C#规则与LSP不完全匹配(不幸的是,这主要是在C#中犯的错误,并被复制到C#中以帮助讨好Java程序员)。另一方面,在运行时必须遵循LSP规则,因此如果您从这些规则开始,您将编写编译和正确运行的代码,我认为这比学习C#语言规则更有价值(除非您正在编写C#编译器)。
发布于 2013-04-27 06:44:52
如何确定声明为协变量(out)的类型参数是否具有协变量有效性?
读第3条。
在泛型接口
I{string, object int>的封闭构造接口I<in T, out U, V>中,类型参数object在泛型接口声明中声明为协变类型参数out U这一事实不就意味着类型参数object是协变的吗?
首先,您使用的是“协变量”,意思是“共同有效”。记住,这些是不同的东西。
第二,让我们再看一遍。object是否共同有效?是的,根据规则1. I<string, object, int>是否共同有效?是的,第3条规定:
由于满足了所有三个条件,所以I<string, object, int>是共同有效的。
在“数组类型T[],其中T是有效的协变”中,数组元素类型T是有效的协变量意味着什么?
我不明白这个问题。我们正在定义“共同有效”的含义。第2条是“共同有效”定义的一部分。
例如,object[]是否是共同有效的?是的,因为object是共同有效的。如果我们有:
interface IFoo<out T> { T[] M(); }T[]是否共同有效?是的,因为T是共同有效的。
如果我们有
interface IBar<in T> { T[] M(); }T[]是否共同有效?不是的。若要使数组类型具有协变量有效性,则其元素类型必须是协变量有效的,但T无效。
https://stackoverflow.com/questions/16246281
复制相似问题