Generic Covariance& Contra-variance在C#4.0中实现?

时间:2008-10-29 02:27:19

标签: c# c#-4.0 covariance contravariance generic-variance

我没有参加PDC 2008,但我听到一些消息称C#4.0被宣布支持Generic协方差和反差异。也就是说,List<string>可以分配给List<object>。怎么会这样?

在Jon Skeet的书 C#in Depth 中,解释了为什么C#泛型不支持协方差和反方差。它主要用于编写安全代码。现在,C#4.0改为支持它们。它会带来混乱吗?

有人知道有关C#4.0的详细信息可以给出一些解释吗?

2 个答案:

答案 0 :(得分:154)

只有安全方式支持差异 - 实际上,使用CLR已有的功能。因此,我在试图使用List<Banana>作为List<Fruit>(或其他任何内容)的书中提供的示例仍然不起作用 - 但其他几种情况也会如此。

首先,它只支持接口和代理。

其次,它要求interface / delegate的作者将类型参数装饰为in(用于逆变)或out(用于协方差)。最明显的例子是IEnumerable<T>,它只允许你“取出”它的值 - 它不允许你添加新的值。那将成为IEnumerable<out T>。这根本不会损害类型安全性,但允许您从声明为返回IEnumerable<string>的方法返回IEnumerable<object>

使用接口更难以给出具体的示例,但是使用委托很容易。考虑Action<T> - 它只代表一个采用T参数的方法。能够无缝转换使用Action<object>作为Action<string>会很高兴 - 任何带object参数的方法在显示string时都会正常而是。当然,C#2在某种程度上已经具有代表的协方差和逆变,但是通过从一个委托类型到另一个委托类型的实际转换(创建新实例) - 参见P141-144的示例。 C#4将使这更通用,并且(我相信)将避免为转换创建新实例。 (相反,它将是一个参考转换。)

希望这有点清除 - 如果没有意义,请告诉我!

答案 1 :(得分:5)

并不是说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

https://www.youtube.com/watch?v=XRIadQaBYlI

https://www.youtube.com/watch?v=St9d2EDZfrg