我正在研究 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
这实际上与速度无关(如您所建议的),更多与隐式转换有关,您可以在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);
当重载决策规则(§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
或者你的例子
int a = 1;
float b = 1.0f;
WriteLine((float)a==b); // promotes a to float
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句