编译器应该翻译此代码:
public static explicit operator Int64(MyNumber n)
{
return n.ToInteger();
}
public static explicit operator Double(MyNumber n)
{
return n.ToDouble();
}
两个具有相同名称和签名但仅由返回类型不同的方法,例如
public static Int64 ExplicitCast(MyNumber n)
...
public static Double ExplicitCast(MyNumber n)
...
但是,我们不允许使用只有返回类型不同的方法。窗帘背后会发生什么?
答案 0 :(得分:7)
从技术上讲,CLS(公共语言规范,指定所有.NET语言应支持的.NET虚拟机的子部分的规范)表示显式强制转换方法的名称应为op_Explicit
(请参阅例如http://goo.gl/wn8dHq)。
您可以使用多个具有相同名称且只有不同返回类型的方法的限制是C#的限制。 IL语言(即.NET虚拟机的语言)没有此限制。
例如参见:https://stackoverflow.com/a/442100/613130
但是,某些语言(例如MSIL)允许按返回类型进行重载。他们当然也面临上述困难,但他们有解决方法,您必须查阅他们的文档。
和https://blogs.msdn.microsoft.com/abhinaba/2005/10/07/c-cil-supports-overloading-by-return-type/
但是,CIL确实支持按返回类型重载方法,即使C#,VB没有。实现转换运算符重载C#编译器使用此功能(我知道一种用法,我确信还有更多:))
(这就是这里提到的情况)
如果您想查看ECMA-335标准:
I.8.11.1方法定义
方法签名定义了调用约定,类型 方法的参数和方法的返回类型
如果您有兴趣知道如何调用该方法......那么......很明显,如果IL语言支持返回类型的重载,那么它的call
指令必须支持它: - )
call int64 MyNumber::op_Explicit(class MyNumber)
VS
call float64 MyNumber::op_Explicit(class MyNumber)
请注意,CLS通常仅根据返回类型禁止重载...但它有op_Implicit
(隐式强制转换运算符)和op_Explicit
(显式强制转换运算符)的异常(来自同一个) ECMA-335文件):
CLS规则38:属性和方法只能根据数量和类型重载 它们的参数,除了名为op_Implicit和op_Explicit的转换运算符之外 也可以根据返回类型重载。
答案 1 :(得分:1)
我不确定你问题的目的,所以这是我能给你的最佳答案。上面的代码编译成这样的
MyNumber.op_Explicit:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt UserQuery+MyNumber.ToInteger
IL_0007: stloc.0
IL_0008: br.s IL_000A
IL_000A: ldloc.0
IL_000B: ret
MyNumber.op_Explicit:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt UserQuery+MyNumber.ToDouble
IL_0007: stloc.0
IL_0008: br.s IL_000A
IL_000A: ldloc.0
IL_000B: ret
它出现的原因"不一致"是因为关键字explicit operator
。它告诉编译器生成代码的方式与显式转换中的代码不同。
如果没有它,你会得到这样的东西:
MyNumber.Double2:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt UserQuery+MyNumber.ToDouble
IL_0007: stloc.0
IL_0008: br.s IL_000A
IL_000A: ldloc.0
IL_000B: ret