真的不可能使用返回类型重载?

dev*_*ium 11 .net c#

我用两种方法在MSIL中创建了一个小DLL:

float AddNumbers(int, int)
int AddNumbers(int, int)
Run Code Online (Sandbox Code Playgroud)

正如你们可能知道的那样,MSIL允许你创建具有相同参数的方法,只要你有不同类型的返回类型(所谓的返回类型重载).现在,当我尝试从c#中使用它时,正如我所期待的那样,它发出错误:

float f = ILasm1.MainClass.AddNumbers(1, 2);
Run Code Online (Sandbox Code Playgroud)

错误是:

以下方法或属性之间的调用不明确:'ILasm1.MainClass.AddNumbers(int,int)'和'ILasm1.MainClass.AddNumbers(int,int)'

c#真的无法区分不同的返回类型吗?我知道我不能编写只有不同返回类型的方法,但我总是认为它会知道如何处理它.

Tob*_*nen 21

ECMA-334 C#第8.7.3节

方法的签名包括方法的名称以及其形式参数的数量,修饰符和类型.方法的签名不包括返回类型.

您可以使用通用方法:

T AddNumbers<T>(int a, int b)
{
   if (typeof(T) == typeof(int) || typeof(T) == typeof(float))
   {
      return (T)Convert.ChangeType(a + b, typeof(T));
   }

   throw new NotSupportedException();
}
Run Code Online (Sandbox Code Playgroud)


Hen*_*man 18

是的,在C#中真的不可能,我知道C++也不允许这样做,它与语句的解释方式有关:

double x = AddNumbers(1, 2);
Run Code Online (Sandbox Code Playgroud)

这里的规则是赋值是右关联的,意味着右边的表达式首先被完全评估,然后才考虑赋值,在必要时应用隐式转换.

编译器无法确定哪个版本最合适.使用一些任意规则只会招来很难找到错误.

它与这个简单的陈述有关:

double y = 5 / 2;  // y = 2.0
Run Code Online (Sandbox Code Playgroud)

  • 双重的好例子. (2认同)

Rub*_*ben 18

像其他人一样,没有C#不支持这一点.实际上,IL支持这个的原因是因为你必须明确返回类型,就像参数一样.例如,在IL你会说

ldarg.0
ldarg.1
call int AddNumbers(int, int)
Run Code Online (Sandbox Code Playgroud)

IL实际上没有方法重载的概念:float AddNumbers(int, int)int AddNumbers(int, int)IL而言,与任何方面无关.你必须提前告诉IL编译器,它永远不会试图推断你的意图(比如像C#这样的高级语言).

请注意,大多数.NET语言和C#都会返回类型重载的一个例外:转换运算符.所以

public static explicit operator B(A a);
public static explicit operator C(A a);
Run Code Online (Sandbox Code Playgroud)

编译成

public static B op_Explicit(A a);
public static C op_Explicit(A a);
Run Code Online (Sandbox Code Playgroud)

因为这是一个特殊的极端情况,必须支持原始类型(例如int - > bool)和引用类型转换(否则你会得到一种非常迂腐的语言),这是处理,但不是作为一个案例方法重载.