在C#4.0中如何实现generics协方差和对数变异?
我没有参加PDC 2008,但是我听到一些消息说C#4.0被宣布支持Generic协方差和反方差。 也就是说, List<string>
可以被分配给List<object>
。 那怎么可能?
在Jon Skeet的书“ 深度C#”中 ,解释了为什么C#generics不支持协方差和反方差。 主要是为了编写安全的代码。 现在,C#4.0更改为支持它们。 会不会带来混乱?
有人知道关于C#4.0的细节可以给一些解释吗?
只有以安全的方式支持差异 – 事实上,使用CLR已具备的能力。 所以我在试图使用List<Banana>
作为List<Fruit>
(或其它)的List<Banana>
中所给出的示例仍然不起作用 – 但是其他一些情况将会如此。
首先,它只支持接口和代表。
其次,它需要接口/委托的作者来装饰types参数,如(逆变换)或out
(协方差)。 最明显的例子是IEnumerable<T>
,它只能让你把值“取出” – 它不会让你添加新的值。 这将成为IEnumerable<out T>
。 这根本不会伤害types安全性,但可以让您从声明为返回IEnumerable<object>
的方法返回IEnumerable<string>
。
逆变更难以给出使用接口的具体示例,但使用委托很容易。 考虑Action<T>
– 这只是表示一个采用T
参数的方法。 能够将Action<object>
无缝地转换为Action<string>
是很好的 – 任何采用object
参数的方法在用string
表示时都会很好。 当然,C#2在某种程度上已经具有代表的协变性和相反性,但是通过从一个委托types到另一个委托types(创build一个新实例)的实际转换 – 例子见P141-144。 C#4将使这个更通用,并且(我相信)将避免为转换创build一个新的实例。 (这将是一个参考转换。)
希望这个清除了一点 – 请让我知道,如果没有任何意义!
这并不是说Jon还没有涉及,但是这里有一些链接到Eric Lippert的博客和video。 他做了很好的例子解释。
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
video:
https://www.youtube.com/watch?v=3MQDrKbzvqU