我用两种方法在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)
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)和引用类型转换(否则你会得到一种非常迂腐的语言),这是处理,但不是作为一个案例方法重载.
| 归档时间: |
|
| 查看次数: |
4606 次 |
| 最近记录: |