我第一次遇到这些术语:C#语言规范的方差安全部分中的输出安全,输入安全,输出不安全和输入不安全。我熟悉方差的概念(协方差和逆变),它基本上是指用一种类型代替另一种类型。
那么输出或输入安全的真正含义是什么?我们是在讨论泛型类型中的类型参数还是任何类型(引用或值)?
答案 0 :(得分:12)
这部分规范 - 你指的是C#4规范的第13.1.3.1节,也许你应该在你的问题的某处提到 - 是不幸的,我道歉。 Mads和我的意思很好,但我从来没有对这部分规范的结果感到兴奋。
我们试图为C#规范提出一个更直观,易于理解的“covariantly valid”,“contravariantly valid”和“invariantly valid”的描述;原始草案规范是用这些术语编写的,人们发现这些术语令人困惑。结果实际上并不容易理解,它包含一些错误。
我的建议是:如果您需要了解变体界面的有效或无效的准确规则,那么您应该阅读我在这个主题上的注释:
http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx
这实际上是我在实现该功能时所做的注释的注释转录。这些注释要比规范中最后的文本更详细,更有希望。
您可能还想阅读CLI规范中的相关部分;我的笔记直接基于对它的全面阅读。
要真正回答你的问题:“输出不安全”和“输入不安全”背后的想法基本上就是如果你有:
interface I<in T>
{
T M();
}
然后T
无法安全地用于输出位置。假设我们允许这个;这样做会违反类型安全:
class C : I<Animal>
{ public Animal M() { return new Giraffe(); } }
...
I<Animal> ia = new C<Animal>();
I<Tiger> it = ia; // Contravariant!
Tiger t = it.M(); // We just assigned a giraffe to a variable of type tiger.
这违反了类型安全,因此我们说T
是“输出不安全”,因此此接口无效,因为输出中使用了明显的T
位置。类似地,“输入不安全”:
interface I<out T>
{
void M(T t);
}
你可以制作一只带有长颈鹿的I<Giraffe>
,将它转换为I<Animal>
并将老虎传给M
,这是不安全的。 T
输入不安全,因此在输入位置使用T
的此接口无效。