为什么 C#/CLR 不支持方法覆盖协变/逆变?

发布于 2024-07-20 05:41:39 字数 209 浏览 6 评论 0原文

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

对于扩大访问参数,可能会提出类似的问题 - 例如,用公共方法覆盖受保护的内部方法(Java 支持的东西,IIRC)

There are quite a few questions & answers about hacking around the limitation of C# not allowing method return (and argument) types to be changed to compatible types on overrides, but why does this limitation exist, either in the C# compiler or in the CLR? As I an see, there is nothing that could break if co/contra-variance was allowed, so what is the reasoning behind it?

A similar question could be asked for widening access parameters - eg overriding a protected internal method with a public method (something which Java supports, IIRC)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

年华零落成诗 2024-07-27 05:41:39

这个答案不是在谈论 C#,但它帮助我更好地理解问题,也许它会帮助其他人: 为什么没有参数对立 -覆盖的方差?

This answer is not talking about C#, but it helped me understand the issues better and maybe it will help others: Why is there no parameter contra-variance for overriding?

梦屿孤独相伴 2024-07-27 05:41:39

埃里克·利珀特(Eric Lippert)已经比我更好地回答了这个问题。

查看他的系列 C# 中的协变和逆变

如何实现C# 4.0 通用协方差 & 实现了逆变?

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

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

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

我强烈怀疑这个答案
关键在于CLR的实现
而不是任何深层语义
原因 - CLR 可能需要
知道是否会
是一个返回值,以便执行
与堆栈适当的东西。
即便如此,似乎还是有些遗憾,
优雅方面。 我不能说我已经
曾经真正感受到过这个必要性
生活,这将是相当容易的
伪造(最多四个参数)
.NET 3.5 只需编写一个转换器
FuncActionFunc
Action 等。它有点麻烦
虽然:)

Eric Lippert already answered this way better than I could.

Check out his series on Covariance and Contravariance in C#

and

How does C# 4.0 Generic Covariance & Contra-variance Implmeneted?

EDIT: Eric pointed out that he doesn't talk about return type convariance but I decided to keep the link in this answer because it is a cool series of articles and someone might find it useful if looking up this topic.

This feature has been requested and almost 5 years ago Microsoft has responded with "Thanks for logging this. We hear this request a lot. We'll consider it for the next release."

And now I'll quote Jon Skeet because it would not be a proper answer on StackOverflow without an answer by Jon Skeet. Covariance and void return types

I strongly suspect that the answer
lies in the implementation of the CLR
rather than in any deep semantic
reason - the CLR probably needs to
know whether or not there's going to
be a return value, in order to do
appropriate things with the stack.
Even so, it seems a bit of a pity, in
terms of elegance. I can't say I've
ever felt the need for this in real
life, and it would be reasonably easy
to fake (for up to four parameters) in
.NET 3.5 just by writing a converter
from Func<X> to Action<X>, Func<X,Y>
to Action<X,Y> etc. It niggles a bit
though :)

沒落の蓅哖 2024-07-27 05:41:39

引入返回值协方差的 Seams 没有 Java 和 C++ 所使用的本质缺点。 然而,引入形式参数的逆变确实会造成混乱。 我认为 C++ 中的这个答案 https://stackoverflow.com/a/3010614/1443505 对于 C# 也有效。

Seams introducing covariance of return value has no essential drawback as Java and C++ have used. However, there's real confusion cased by introducing contra-variance of formal parameter. I think this answer https://stackoverflow.com/a/3010614/1443505 in C++ is also valid for C#.

伴我老 2024-07-27 05:41:39

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

It does, you just have to wait for VS2010/.Net 4.0.

何以笙箫默 2024-07-27 05:41:39

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

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

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

只要参数等也都是公开的)-有什么用吗?

To expand on Joel's answer - the CLR has supported limited variance for a long time, but the C# compiler doesn't use them until 4.0 with the new "in" and "out" modifiers on generic interfaces and delegates. The reasons are complicated, and I would get into a mess trying to explain, but it isn't as simple as it seems.

Re making a "protected internal" method into a "public" method; you can do this with method hiding:

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

(as long as the arguments etc are all also public) - any use?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文