有很多关于绕过C#不允许方法返回(和参数)类型在重写时更改为兼容类型的限制的问题和答案,但是 为什么 要存在这种限制,无论是在C#编译器还是CLR中?据我所知,如果允许共变性/逆变性,没有任何可能会导致错误的情况,因此背后的原因是什么呢?
类似的问题也可以针对扩大访问参数进行提问-例如使用公共方法覆盖受保护的内部方法(Java支持此操作,如果我没记错的话)。
有很多关于绕过C#不允许方法返回(和参数)类型在重写时更改为兼容类型的限制的问题和答案,但是 为什么 要存在这种限制,无论是在C#编译器还是CLR中?据我所知,如果允许共变性/逆变性,没有任何可能会导致错误的情况,因此背后的原因是什么呢?
类似的问题也可以针对扩大访问参数进行提问-例如使用公共方法覆盖受保护的内部方法(Java支持此操作,如果我没记错的话)。
Eric Lippert已经比我回答得更好了。
请查看他关于C#中协变和逆变的系列文章Covariance and Contravariance in C#
以及
How does C# 4.0 Generic Covariance & Contra-variance Implmeneted?
编辑:Eric指出他并没有讨论返回类型协变,但我决定在这个答案中保留链接,因为这是一系列很棒的文章,如果有人查找这个主题可能会发现它有用。
这个功能已经被请求, 近5年前,Microsoft回应说:“感谢您记录这个。我们经常听到这个请求。我们将考虑在下一个版本中实现它。”
现在我引用Jon Skeet的话,因为如果没有Jon Skeet的答案,StackOverflow上就不会是一个合适的答案。 Covariance and void return types
我强烈怀疑答案在CLR的实现中而不是在深层语义原因中 - CLR可能需要知道是否会有返回值,以便对栈进行适当处理。即使如此,在优雅方面似乎有点可惜。我不能说我在现实生活中曾经有过这种需求,而且在.NET 3.5中可以通过编写从
Func<X>
到Action<X>
,Func<X,Y>
到Action<X,Y>
等的转换器来伪造(最多四个参数)。但这有点令人不爽 :)
似乎引入返回值的协变性没有Java和C++使用的本质缺陷。然而,引入形式参数的逆变性确实会导致真正的混淆。我认为这个C++中的答案 https://dev59.com/p3A75IYBdhLWcg3w_ef1#3010614 对于C#也是有效的。
有的,你只需要等待VS2010/.Net 4.0。
public new void Foo(...) { base.Foo(...); }
只要参数等也是公共的,这样使用可以吗?