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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/245607/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:40:35  来源:igfitidea点击:

How is Generic Covariance & Contra-variance Implemented in C# 4.0?

c#c#-4.0covariancecontravariancegeneric-variance

提问by Morgan Cheng

I didn't attend PDC 2008, but I heard some news that C# 4.0 is announced to support Generic covariance and contra-variance. That is, List<string>can be assigned to List<object>. How could that be?

我没有参加 PDC 2008,但我听说 C# 4.0 宣布支持通用协变和逆变的消息。也就是说,List<string>可以赋值给List<object>。怎么会这样?

In Jon Skeet's book C# in Depth, it is explained why C# generics doesn't support covariance and contra-variance. It is mainly for writing secure code. Now, C# 4.0 changed to support them. Would it bring chaos?

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

Anybody know the details about C# 4.0 can give some explanation?

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

采纳答案by Jon Skeet

Variance will only be supported in a safeway - in fact, using the abilities that the CLR already has. So the examples I give in the book of trying to use a List<Banana>as a List<Fruit>(or whatever it was) still won't work - but a few other scenarios will.

仅以安全的方式支持差异- 实际上,使用 CLR 已有的功能。所以我在书中给出的尝试将 aList<Banana>用作 a List<Fruit>(或任何它是)的例子仍然不起作用 - 但其他一些场景会起作用。

Firstly, it will only be supported for interfaces and delegates.

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

Secondly, it requires the author of the interface/delegate to decorate the type parameters as in(for contravariance) or out(for covariance). The most obvious example is IEnumerable<T>which only ever lets you take values "out" of it - it doesn't let you add new ones. That will become IEnumerable<out T>. That doesn't hurt type safety at all, but lets you return an IEnumerable<string>from a method declared to return IEnumerable<object>for instance.

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

Contravariance is harder to give concrete examples for using interfaces, but it's easy with a delegate. Consider Action<T>- that just represents a method which takes a Tparameter. It would be nice to be able to convert seamlessly use an Action<object>as an Action<string>- any method which takes an objectparameter is going to be fine when it's presented with a stringinstead. Of course, C# 2 already has covariance and contravariance of delegates to some extent, but via an actual conversion from one delegate type to another (creating a new instance) - see P141-144 for examples. C# 4 will make this more generic, and (I believe) will avoid creating a new instance for the conversion. (It'll be a reference conversion instead.)

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

Hope this clears it up a bit - please let me know if it doesn't make sense!

希望这能让我明白一点 - 如果它没有意义,请告诉我!

回答by kemiller2002

Not that Jon hasn't already covered it, but here are some links to blogs and videos from Eric Lippert. He does a nice job of explaining it with examples.

并不是说 Jon 还没有涵盖它,但这里有一些指向 Eric Lippert 的博客和视频的链接。他用例子很好地解释了它。

https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/

https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/

The videos:

视频:

https://www.youtube.com/watch?v=3MQDrKbzvqU

https://www.youtube.com/watch?v=3MQDrKbzvqU

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

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

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

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