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

时间:2019-04-11 03:01:28

标签: c# .net cil system.reflection

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

我发现两种不同原始类型之间使用==运算符的行为难以理解。

int a = 1;
float b = 1.0f;        
Console.WriteLine(a == b);

这实际上是编译为

.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

这意味着

(float)a == (float)b

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

任何原因导致此结果?


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

1 个答案:

答案 0 :(得分:8)

这确实与 speed (如您所建议的)无关,而与隐式转换无关,您可以找到在<主题下定义的相关信息C# Specifications

中的em>数字促销
  

12.4.7数字促销

     

数字促销自动执行某些   预定义的一元操作数隐式转换    binary 数字运算符 数字促销并非唯一   机制,而是将过载分辨率应用于   预定义的操作员数字促销特别不影响   用户定义的 operators 的用户评估   可以实现类似的效果。

     

作为数字促销的示例,请考虑预定义的   二进制* operator

的实现
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);
     

超载分辨率规则(第12.6.4节)应用于这组运算符时,效果是选择中的第一个运营商    operand 类型存在哪些隐式转换

更多

  预定义的+的操作数出现

二进制数字提升,   */%&|^==,{{ 1}},!=><>=二进制运算符。   二进制数值提升将两个操作数隐式转换为通用   在非关系运算符的情况下,它也变为   操作的结果类型。二进制数值提升包括   按照出现的顺序应用以下规则:

     
      
  • 如果任一操作数的类型为小数,则另一个操作数将转换为十进制类型,或者如果另一个操作数为十进制,则发生绑定时间错误   类型为float或double。
  •   
  • 否则,如果其中一个操作数为double类型,则另一个操作数将转换为double类型。
  •   
  • 否则,如果其中一个操作数为float类型,则另一个操作数将转换为float类型。
  •   
  • 否则,如果其中一个操作数为ulong类型,则另一个操作数将转换为ulong类型,或者如果另一个操作数为ulong类型,则发生绑定时错误   操作数的类型为sbyte,short,int或long。
  •   
  • 否则,如果其中一个操作数为long类型,则另一个操作数将转换为long类型。
  •   
  • 否则,如果一个操作数的类型为uint而另一个操作数的类型为sbyte,short或int,则两个操作数都将转换为类型   长。
  •   
  • 否则,如果其中一个操作数的类型为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