5

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

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

4

1 回答 1

13

规范的这一部分——你指的是 C# 4 规范的第 13.1.3.1 节,也许你应该在问题的某个地方提到它——很不幸,我深表歉意。Mads 和我的意思很好,但我从来没有对规范的这一部分结果感到兴奋。

我们试图为 C# 规范提出“协变有效”、“逆变有效”和“不变有效”的更直观和易于理解的描述;最初的规范草案是用这些术语编写的,人们发现这些术语令人困惑。结果实际上并不太容易理解,并且包含一些错误。

我的建议是:如果您需要了解使变体接口有效或无效的确切规则,那么您应该阅读我关于此主题的注释:

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在输入位置使用的这个接口是无效的。

于 2013-04-23T22:56:53.037 回答