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->float比float->int这实际上与速度无关(如您所建议),而与隐式转换无关,您可以在C#规范的“ 数字促销 ”主题下找到定义的相关信息。
12.4.7数字促销
数值提升包括自动执行预定义的一元和 二进制数值运算符的操作数的某些 隐式转换。数值提升不是独特的机制,而是将重载分辨率应用于预定义运算符的效果。尽管 可以将用户定义的运算符实现为具有相似的效果,但是数字提升不会特别影响用户定义的运算符的评估。
作为数字提升的示例,请考虑二进制* 运算符的预定义实现:
Run Code Online (Sandbox Code Playgroud)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
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)
| 归档时间: |
|
| 查看次数: |
81 次 |
| 最近记录: |