为什么C#/ CLR不支持方法覆盖co / contra-variance?

时间:2023-01-15 20:39:18

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?

关于C#限制的黑客攻击有很多问题和答案,不允许在重写时将方法返回(和参数)类型更改为兼容类型,但为什么在C#编译器或CLR中存在这种限制?正如我所看到的,如果允许共同/反向差异,没有什么可以破坏,那么背后的原因是什么呢?

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)

可以要求扩展访问参数的类似问题 - 例如,使用公共方法覆盖受保护的内部方法(Java支持的内容,IIRC)

5 个解决方案

#1


3  

Eric Lippert already answered this way better than I could.

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

Check out his series on Covariance and Contravariance in C#

看看他在C#中关于协方差和逆变的系列

and

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

C#4.0通用协方差和反差方法如何发挥作用?

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."

这个功能已被要求,差不多5年前,微软已经回复了“感谢你记录这个。我们听到了很多这样的要求。我们会在下一个版本中考虑它。”

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

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

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 :)

我强烈怀疑答案在于CLR的实现,而不是任何深层次的语义原因 - CLR可能需要知道是否会有返回值,以便对堆栈做适当的事情。即便如此,在优雅方面似乎有点可惜。我不能说我曾经在现实生活中感受到这一点,并且只需将Func 中的转换器写入Action <,在.NET 3.5中伪造(最多四个参数)就相当容易了X>,Func 来行动 等等虽然有点摇晃:) ,y> ,y>

#2


2  

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?

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

#3


0  

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://*.com/a/3010614/1443505 in C++ is also valid for C#.

引入返回值协方差的接缝没有基本的缺点,因为Java和C ++已经使用过。然而,通过引入形式参数的逆变量,存在真正的混淆。我认为这个答案https://*.com/a/3010614/1443505在C ++中也适用于C#。

#4


-1  

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

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

#5


-1  

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.

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

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?

(只要论点等都是公开的) - 任何用途?

#1


3  

Eric Lippert already answered this way better than I could.

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

Check out his series on Covariance and Contravariance in C#

看看他在C#中关于协方差和逆变的系列

and

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

C#4.0通用协方差和反差方法如何发挥作用?

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."

这个功能已被要求,差不多5年前,微软已经回复了“感谢你记录这个。我们听到了很多这样的要求。我们会在下一个版本中考虑它。”

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

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

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 :)

我强烈怀疑答案在于CLR的实现,而不是任何深层次的语义原因 - CLR可能需要知道是否会有返回值,以便对堆栈做适当的事情。即便如此,在优雅方面似乎有点可惜。我不能说我曾经在现实生活中感受到这一点,并且只需将Func 中的转换器写入Action <,在.NET 3.5中伪造(最多四个参数)就相当容易了X>,Func 来行动 等等虽然有点摇晃:) ,y> ,y>

#2


2  

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?

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

#3


0  

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://*.com/a/3010614/1443505 in C++ is also valid for C#.

引入返回值协方差的接缝没有基本的缺点,因为Java和C ++已经使用过。然而,通过引入形式参数的逆变量,存在真正的混淆。我认为这个答案https://*.com/a/3010614/1443505在C ++中也适用于C#。

#4


-1  

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

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

#5


-1  

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.

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

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?

(只要论点等都是公开的) - 任何用途?