13

有很多关于破解 C# 的限制的问题和答案,不允许方法返回(和参数)类型在覆盖时更改为兼容类型,但为什么在 C# 编译器或 CLR 中存在此限制?如我所见,如果允许协方差,没有什么可以破坏的,那么它背后的原因是什么?

可以询问类似的问题来扩大访问参数 - 例如用公共方法覆盖受保护的内部方法(Java支持的东西,IIRC)

4

5 回答 5

3

Eric Lippert 已经比我更好地回答了这个问题。

查看他关于C# 中的协变和逆变的系列文章

C# 4.0 Generic Covariance & Contra-variance 是如何实现的?

编辑:埃里克指出他没有谈论返回类型的协变,但我决定在这个答案中保留链接,因为这是一个很酷的系列文章,如果查找这个主题,有人可能会发现它很有用。

此功能已被请求,大约 5 年前,Microsoft 已回复“感谢您记录此功能。我们经常听到此请求。我们将在下一个版本中考虑它。”

现在我将引用 Jon Skeet,因为如果没有 Jon Skeet 的回答,它就不是 StackOverflow 上的正确答案。协方差和 void 返回类型

我强烈怀疑答案在于 CLR 的实现,而不是任何深层的语义原因 - CLR 可能需要知道是否会有返回值,以便对堆栈执行适当的操作。即便如此,就优雅而言,这似乎有点可惜。我不能说我在现实生活中曾经觉得需要这样做,而且只需编写一个从Func<X>to 到 to等的转换器Action<X>,在 .NET 3.5 中伪造(最多四个参数)是相当容易的。它很琐碎虽然有点:)Func<X,Y>Action<X,Y>

于 2009-05-07T21:41:01.103 回答
2

这个答案不是在谈论 C#,但它帮助我更好地理解了这些问题,也许它会帮助其他人:为什么没有用于覆盖的参数逆变?

于 2011-07-05T14:08:42.520 回答
0

引入返回值协方差的 Seams 没有 Java 和 C++ 使用过的本质缺陷。然而,引入形式参数的逆变会引起真正的混乱。我认为 C++ 中的这个答案https://stackoverflow.com/a/3010614/1443505也适用于 C#。

于 2015-04-13T05:20:58.860 回答
-1

确实如此,您只需要等待 VS2010/.Net 4.0。

于 2009-05-07T21:30:48.307 回答
-1

为了扩展 Joel 的答案 - CLR 长期以来一直支持有限的变化,但 C# 编译器直到 4.0 才使用它们,并在通用接口和委托上使用新的“in”和“out”修饰符。原因很复杂,我会陷入混乱试图解释,但这并不像看起来那么简单。

将“受保护的内部”方法重新制作为“公共”方法;你可以通过隐藏方法来做到这一点:

public new void Foo(...) { base.Foo(...); }

(只要论点等都是公开的) - 有什么用吗?

于 2009-05-07T21:40:36.597 回答