我没有参加 PDC 2008,但我听说 C# 4.0 宣布支持通用协变和逆变换的消息。也就是说,List<string>
可以分配给List<object>
。怎么可能?
在 Jon Skeet 的C# in Depth一书中,解释了为什么 C# 泛型不支持协变和逆变。它主要用于编写安全代码。现在,C# 4.0 更改为支持它们。会不会带来混乱?
有人知道有关 C# 4.0 的详细信息可以给出一些解释吗?
我没有参加 PDC 2008,但我听说 C# 4.0 宣布支持通用协变和逆变换的消息。也就是说,List<string>
可以分配给List<object>
。怎么可能?
在 Jon Skeet 的C# in Depth一书中,解释了为什么 C# 泛型不支持协变和逆变。它主要用于编写安全代码。现在,C# 4.0 更改为支持它们。会不会带来混乱?
有人知道有关 C# 4.0 的详细信息可以给出一些解释吗?
仅以安全的方式支持 Variance - 事实上,使用 CLR 已有的功能。因此,我在书中给出的尝试将 aList<Banana>
用作List<Fruit>
(或其他任何东西)的示例仍然不起作用 - 但其他一些场景会起作用。
首先,它只支持接口和委托。
其次,它要求接口/委托的作者将类型参数装饰为in
(用于逆变)或out
(用于协变)。最明显的例子是IEnumerable<T>
它只允许你从其中“取出”值——它不允许你添加新的值。那会变成IEnumerable<out T>
. 这根本不会损害类型安全,但可以让您IEnumerable<string>
从声明为返回的方法中返回一个IEnumerable<object>
例如。
逆变很难给出使用接口的具体示例,但使用委托很容易。考虑一下Action<T>
- 这只是表示一个带有T
参数的方法。能够无缝转换使用 an Action<object>
as an会很好Action<string>
- 任何采用object
参数的方法在使用 a 时都会很好string
。当然,C# 2 已经在某种程度上具有委托的协变和逆变,但是通过从一种委托类型到另一种委托类型的实际转换(创建一个新实例) - 参见 P141-144 示例。C# 4 将使这更通用,并且(我相信)将避免为转换创建新实例。(这将是一个参考转换。)
希望这能澄清一点 - 如果它没有意义,请告诉我!
并不是说 Jon 还没有介绍过它,但这里有一些指向 Eric Lippert 的博客和视频的链接。他用例子很好地解释了它。
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
视频:
https://www.youtube.com/watch?v=3MQDrKbzvqU