简体   繁体   English

C#编译器如何处理重载显式转换运算符?

[英]How does the C# compiler handle overloading explicit cast operators?

The compiler should translate this code: 编译器应该翻译这段代码:

public static explicit operator Int64(MyNumber n)
{
    return n.ToInteger();
}

public static explicit operator Double(MyNumber n)
{
    return n.ToDouble();
}

to two methods that have the same name and signature but differ only by their return type, eg 两个方法具有相同的名称和签名,但只有它们的返回类型不同,例如

public static Int64 ExplicitCast(MyNumber n)
...

public static Double ExplicitCast(MyNumber n)
...

However, we are not allowed to have methods that differ only by their return type. 但是,我们不允许只有返回类型的方法。 What happens behind the curtains? 窗帘背后会发生什么?

Technically the CLS (the Common Language Specification, a specification that specify a subsect of the .NET virtual machine that all .NET languages should support) says that the name of the explicit cast method should be op_Explicit (see for example http://goo.gl/wn8dHq ). 从技术上讲,CLS(公共语言规范,指定所有.NET语言应该支持的.NET虚拟机的子部分的规范)表示显式op_Explicit方法的名称应该是op_Explicit (参见例如http:// goo .gl / wn8dHq )。

The limitation that you can't have multiple methods with the same name and only different return types is a limitation of C#. 您不能拥有多个具有相同名称且只有不同返回类型的方法的限制是C#的限制。 The IL language (that is the language of the .NET virtual machine) doesn't have this limitation. IL语言(即.NET虚拟机的语言)没有此限制。

See for example: https://stackoverflow.com/a/442100/613130 例如,请参阅: https//stackoverflow.com/a/442100/613130

Some languages (such as MSIL), however, do allow overloading by return type. 但是,某些语言(例如MSIL)允许通过返回类型进行重载。 They too face the above difficulty of course, but they have workarounds, for which you'll have to consult their documentation. 他们当然也面临上述困难,但他们有解决方法,你必须查阅他们的文档。

and https://blogs.msdn.microsoft.com/abhinaba/2005/10/07/c-cil-supports-overloading-by-return-type/ https://blogs.msdn.microsoft.com/abhinaba/2005/10/07/c-cil-supports-overloading-by-return-type/

However, CIL does support overloading methods by return types, even though C#, VB does not . 但是,CIL确实支持通过返回类型重载方法,即使C#,VB没有。 To implement convertion operator overloading C# compiler uses this feature (I know of one usage and I'm sure that there are more :) ) 实现转换运算符重载C#编译器使用此功能(我知道一种用法,我确信还有更多:))

(that is exactly the case asked here) (这就是这里提到的情况)

If you want to look at the ECMA-335 standard: 如果您想查看ECMA-335标准:

I.8.11.1 Method definitions I.8.11.1方法定义

The method signature defines the calling convention, type of the parameters to the method, and the return type of the method 方法签名定义了调用约定,方法的参数类型以及方法的返回类型

If you are interested to know how the method can be called... Well... Clearly if the IL language supports overload by return type, then its call instruction must support it :-) 如果您有兴趣知道如何调用该方法......那么......很明显,如果IL语言支持返回类型的重载,那么它的call指令必须支持它:-)

For example http://goo.gl/CS4FPb : 例如http://goo.gl/CS4FPb

call int64 MyNumber::op_Explicit(class MyNumber)

vs VS

call float64 MyNumber::op_Explicit(class MyNumber)

Note that CLS normally forbids overloading only based on return type... But it has an exception for op_Implicit (the implicit cast operator) and op_Explicit (the explicit cast operator) (from the same ECMA-335 file): 请注意,CLS通常仅根据返回类型禁止重载...但它有一个异常的op_Implicit (隐式转换运算符)和op_Explicit (显式转换运算符)(来自相同的ECMA-335文件):

CLS Rule 38: Properties and methods can be overloaded based only on the number and types of their parameters, except the conversion operators named op_Implicit and op_Explicit, which can also be overloaded based on their return type. CLS规则38:属性和方法可以仅根据其参数的数量和类型进行重载,但名为op_Implicit和op_Explicit的转换运算符除外,它们也可以根据其返回类型进行重载。

I'm not sure the purpose of your question, so this is the best answer I can give you. 我不确定你问题的目的,所以这是我能给你的最佳答案。 The above code compiles to something like this 上面的代码编译成这样的东西

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      

The reason it appears "inconsistent" is because of the keywords explicit operator . 它看起来“不一致”的原因是因为关键字explicit operator It tells the compiler to generate code differently from the way it does in an explicit cast. 它告诉编译器生成代码的方式与在显式转换中的方式不同。

You'd get something like this without it: 没有它,你会得到这样的东西:

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    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM