我正在研究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->float
比float->int
答案 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