为啥 C# 在多态中不考虑函数的返回类型?

Posted

技术标签:

【中文标题】为啥 C# 在多态中不考虑函数的返回类型?【英文标题】:Why does C# not consider the return type of a function in polymorphism?为什么 C# 在多态中不考虑函数的返回类型? 【发布时间】:2014-04-30 05:53:43 【问题描述】:

有两个具有相同名称和相同参数集但返回类型不同的函数。为什么它不是一种多态形式,即方法重载?为什么编译器不允许?

【问题讨论】:

这是一个副本,但是 - 作为旁注 - Ceylon(一种鲜为人知的 JVM 语言)有一个非常有趣的类型系统,它引入了交集和联合类型。请参阅ceylon-lang.org/documentation/current/tour/types 了解更多信息。 @KonradMorawski 如果我错了,请纠正我,但这些功能无助于消除应该调用哪个重载的歧义。最多,它们允许为一组重载提供单一类型。 @delnan 可能你是对的,但仍然 - 如果我理解得很好,我自己从来没有使用过锡兰,只是读过它 - 如果坚持使用 @987654324,它们可以用作一种解决方法@ 和 bool Foo() 并排。 ***.com/questions/442026/… 处理同样的问题。它不是 C# 特定的。 见meta.stackexchange.com/questions/226583/… 【参考方案1】:

因为 C# 被设计成可以从 insideoutside 分析类型。想象一下,如果你有

int N() 
float N()() 

然后打电话

float x = N();

好的,很好,显然我们可以说需要浮动版本。但是你说:

void M(int x) 
void M(float x) 

M(N());

好的,现在需要哪个版本?规则是找出 N() 的含义,然后找出 M 的最佳重载是一旦您知道 N() 的含义。你从内部推理到外部

基于返回类型的重载解析需要从外部内部进行推理,这可能会更困难很多

【讨论】:

+1 : 如果允许返回类型的多态性,那么第一眼阅读和消除代码歧义所需的工作将大大减少。【参考方案2】:

考虑以下几点:

int combine(int a, int b) 
    return a + b;


float combine(int a, int b) 
    return a - b;

如果我要调用 combine(1, 2),编译器将无法知道我要调用这两个方法中的哪一个(这是不明确的)。

您几乎可以提出检查返回类型的理由,但是呢:

var c = combine(1, 2);
dynamic d = combine(1, 2);
combine(1, 2);

在上面,c或d的值应该是多少? 3? -1?这是不可能的。最后一条语句怎么样,没有赋值?我没有定义返回void的重载,那么这两个方法应该调用哪一个呢?

【讨论】:

【参考方案3】:

为了避免呼叫现场的歧义。考虑以下接口:

interface ISomething
  int DoSomething()
  void DoSomething()

当你打电话时

myISomething.DoSomething()

应该调用哪个?

【讨论】:

嗯,它应该调用void,因为你没有将它分配给任何东西。如果这是唯一的原因......你可以举个更好的例子。 @Selman22 :这很愚蠢。您提议更改语言的整个规则,打破向后兼容性并引入额外的检查层,必须简单地进行这些检查才能正确读取代码。这会引入编码错误。归根结底,它就是这样。它不会改变。我更喜欢这种方式。 我没有提出任何建议。我只是说如果这是唯一的问题,编译器可以弄清楚,看看你是否没有将返回结果分配给它可以调用第二种方法的任何东西更合适,那么歧义就会得到解决。【参考方案4】:

因为将返回类型分配给变量不是强制性的。编译器不能强制将返回值分配给变量。即使它强制这样做,停止将整数值分配给浮点数也是没有意义的。如另一个答案所示。

【讨论】:

【参考方案5】:

我相信这可以通过一组复杂的规则(强制明确)来实现,但它会引入许多意外破坏代码的方法。

由于规则的复杂程度不可避免地会带来许多令人困惑的语言怪癖(有点像 php 中的比较运算符)。

值得吗?我们从中得到什么。 “为什么不”的问题应该反过来:为什么是?

【讨论】:

以上是关于为啥 C# 在多态中不考虑函数的返回类型?的主要内容,如果未能解决你的问题,请参考以下文章

请教:C# WebService调用Java WebService(返回Json类型数据) ,为啥接收为null

c++中为啥要用new 函数()实现多态?

为啥多态函数不能在 Scala 中接受通配符(存在)类型?

为啥杰克逊多态序列化在列表中不起作用?

Java中支持多态的方法重载

取决于上下文的多态返回类型