5

在 CLR via c# 第三版中,有一个我似乎无法理解的示例:

不变意味着不能更改该泛型类型参数。到目前为止,我在本章中只展示了不变的泛型类型参数。n

逆变意味着泛型类型参数可以从一个类更改为从它派生的类。在 C# 中,您使用in 关键字指示逆变泛型类型参数。

逆变泛型类型参数只能出现在输入位置,例如方法的参数。n 协变意味着泛型类型参数可以从一个类更改为其基类之一。在 C# 中,您使用out 关键字指示协变泛型类型参数。协变泛型类型参数只能出现在输出位置,例如方法的返回类型。

然后作者继续举这个例子:

public delegate TResult Func<in T, out TResult>(T arg);

这里,泛型类型参数 T 用 in 关键字标记,使其具有逆变性;并且泛型类型参数 TResult 用 out 关键字标记,使其成为协变的

这是我在下一页(292)上遇到问题的地方,然后他在使用界面时说相反。

当使用接受泛型参数和返回值的委托时,建议始终为逆变和协变指定 in 和 out 关键字,因为这样做不会产生不良影响,并使您的委托可以在更多场景中使用。与委托一样,具有泛型类型参数的接口可以使其类型参数是逆变的或协变的。下面是一个带有逆变 >generic 类型参数的接口示例:

public interface IEnumerator<out T> : IEnumerator {
Boolean MoveNext();
T Current { get; }
}

由于 T 是逆变的,因此可以使以下代码编译并成功运行:

// This method accepts an IEnumerable of any reference type
Int32 Count(IEnumerable<Object> collection) { ... }
...
// The call below passes an IEnumerable<String> to Count
Int32 c = Count(new[] { "Grant" });

在第二个示例中,他使用了 out 关键字 ( IEnumerator<out T>),然后将其称为逆变。这是正确的还是我错过了什么。在接口中定义逆变和协变是否有区别?关于这本书,我去过 Oreilly 的网站,但没有列出。

4

2 回答 2

20

out=协变in=逆变

任何与此相反的词都是我书中的错误,我将在以后的版本中更正。

于 2010-07-26T14:05:46.537 回答
9

这是一个错误。这绝对是协方差的一个例子。委托和接口之间的协变和逆变的含义没有区别。

我建议你给 O'Reilly 发邮件报告错误。

于 2010-07-26T12:38:08.387 回答