为什么(int)==(float)总是编译为(float)==(float)

use*_*855 1 .net c# cil system.reflection

我正在研究C#编译器,并试图了解数学运算规则。

我发现==两个不同原始类型之间的运算符行为令人费解。

int a = 1;
float b = 1.0f;        
Console.WriteLine(a == b);
Run Code Online (Sandbox Code Playgroud)

这实际上编译为

.locals init (
    [0] int32,
    [1] float32
)

IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldc.r4 1
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: conv.r4
IL_000b: ldloc.1
IL_000c: ceq
Run Code Online (Sandbox Code Playgroud)

意思是

(float)a == (float)b
Run Code Online (Sandbox Code Playgroud)

我的期望是(int)a == (int)b因为左值是integer

有什么原因导致这种结果?


  • 这是我的猜测:int->floatfloat->int

AAA*_*ddd 8

这实际上与速度无关(如您所建议),而与隐式转换无关,您可以在C#规范的“ 数字促销 ”主题下找到定义的相关信息。

12.4.7数字促销

数值提升包括自动执行预定义的一元二进制数值运算符操作数的某些 隐式转换数值提升不是独特的机制,而是将重载分辨率应用于预定义运算符的效果。尽管 可以将用户定义的运算符实现为具有相似的效果,但是数字提升不会特别影响用户定义的运算符的评估。

作为数字提升的示例,请考虑二进制* 运算符的预定义实现:

int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);
Run Code Online (Sandbox Code Playgroud)

重载决策规则(§12.6.4)施加到该组的运营商该效果是选择第一的运营商针对隐式转换从存在操作数类型。

更进一步

二进制数值提升时为操作数的预定义的+*/%&|^==!=><>=,和<=二元运算符。二进制数值提升将两个操作数隐式转换为通用类型,对于非关系运算符,它也成为运算的结果类型。二进制数值提升包括按照以下规则在此处出现的顺序进行应用:

  • 如果一个操作数的类型为十进制,则另一个操作数的类型将转换为十进制,如果另一个操作数的类型为float或double,则会发生绑定时间错误。
  • 否则,如果其中一个操作数为double类型,则另一个操作数将转换为double类型。
  • 否则,如果其中一个操作数为float类型,则另一个操作数将转换为float类型。
  • 否则,如果一个操作数的类型为ulong,则另一个操作数将转换为ulong类型,或者如果另一个操作数的类型为sbyte,short,int或long,则发生绑定时错误。
  • 否则,如果其中一个操作数的类型为long,则另一个操作数将转换为long类型。
  • 否则,如果一个操作数的类型为uint而另一个操作数的类型为sbyte,short或int,则两个操作数都将转换为long类型。
  • 否则,如果其中一个操作数的类型为uint,则另一个操作数将转换为uint类型。
  • 否则,两个操作数都将转换为int类型。

您可以通过他们展示的示例来感受一下

byte b = 1;
short a = 2;
WriteLine((int)b==(int)s); // promotes both to int

int i = 1;
double d = 2;
WriteLine((double)i==d); // promotes i to double
Run Code Online (Sandbox Code Playgroud)

还是你的例子

int a = 1;
float b = 1.0f; 
WriteLine((float)a==b); // promotes a to float
Run Code Online (Sandbox Code Playgroud)