什么是输出安全或输入安全类型?

时间:2013-04-23 22:42:45

标签: c# variance

我第一次遇到这些术语:C#语言规范的方差安全部分中的输出安全,输入安全,输出不安全和输入不安全。我熟悉方差的概念(协方差和逆变),它基本上是指用一种类型代替另一种类型。

那么输出或输入安全的真正含义是什么?我们是在讨论泛型类型中的类型参数还是任何类型(引用或值)?

1 个答案:

答案 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的此接口无效。