在C#4.0中如何实现通用协方差和反方差?


106

我没有参加PDC 2008,但是我听到一些消息,宣布C#4.0支持通用协方差和反方差。即List<string>可以分配给List<object>。怎么可能

在乔恩·斯基特(Jon Skeet)的《C#in Depth》一书中,解释了为什么C#泛型不支持协方差和逆方差。它主要用于编写安全代码。现在,C#4.0更改为支持它们。会带来混乱吗?

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


这是一篇很好的文章,涵盖了即将在C#4.0中的委托和接口上实现协方差和逆
CMS

AndersNoråse在C#4.0中解释了协方差和反方差的概念,并表明,自.NET 2.0开始,IL已在今天支持该概念。
Thomas Freudenberg,

Answers:


155

仅以安全的方式支持方差-实际上,使用CLR已具备的功能。因此,我在本书中尝试使用a List<Banana>作为List<Fruit>(或其他形式)的示例仍然无法使用-但其他一些情况也可以。

首先,只支持接口和委托。

其次,它要求接口/委托的作者将类型参数修饰inout(对于协方差)或(对于协方差)。最明显的例子是IEnumerable<T>,仅允许您从中“取出”值-不允许添加新值。那将成为IEnumerable<out T>。这根本不会损害类型安全,但是可以让您IEnumerable<string>从声明为要返回的方法中返回IEnumerable<object>

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

希望这能解决问题-如果没有任何意义,请通知我!


3
因此,这是否意味着如果该类被声明为“ List <out T>”,则它不应具有“ void Add(T obj)”之类的成员函数?C#4.0编译器将在此报告错误,对吗?
Morgan Cheng

1
摩根:当然,这是我的理解,是的。
乔恩·斯基特

4
再一次,您在SO上的答案之一立即帮助我改进了一些代码。谢谢!
标记

@方舟坤:是的,我知道。因此,同一句话中的“仍然无法使用”。(而且我也知道原因。)
Jon Skeet 2013年

@JonSkeet List<Banana>IList<Fruit>“ @ Ark-kun”所说,“您只能将a 用作” 是正确的吗?如果是这样,那怎么可能,尽管IList<T>接口的类型参数未定义为协变(no out T,只是简单地T)。
gehho 2013年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.