[英]Why is x = x + 100 treated differently than x += 100 that compiles to the same IL?
我们知道这两个加法语句是等价的,并编译为相同的IL代码:
int x = 100;
x += 100;
x = x + 100;
但是,当需要明确的演员表时我发现了一些奇怪的东西:
byte b = 100;
b += 200; // Compiles (1)
b = b + 200; // Cannot implicitly convert int to byte (2)
b = (byte) (b + 200); // Compiles (3)
很明显,为什么第二个语句需要显式转换,因为加法的结果是整数。 但对我来说奇怪的是第一个声明。 它编译为与第三个语句完全相同的IL,因此看起来编译器为我们添加了一个应该是显式的强制转换。 但它不能在第二个声明中这样做。
这对我来说似乎是矛盾的,因为我希望第一个语句等同于第二个语句并且永远不会编译,所以它为什么要编译?
注意:当从long
到int
需要显式强制转换时,这不会编译:
int x = 100;
long y = 200;
x += y;
你真的需要去了解这类信息的规格 (并且很难理解这些措辞)。 但是,直接从马口
12.18.3复合赋值
x op= y
形式的x op= y
通过应用二元运算符重载决策(第12.4.5节)来处理,就好像操作是在x op y.
中编写的一样x op y.
然后,
如果所选运算符的返回类型可隐式转换为
x
的类型,则操作将计算为x = x op y
,但x仅计算一次。否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为
x
类型,并且如果y
可隐式转换为x
类型或运算符是移位运算符,则操作被评估为x = (T)(x op y)
,其中T
是x
的类型,除了x
仅被计算一次。- 否则,复合赋值无效,并发生绑定时错误。
...
等等等等等等
...
上面的第二条规则允许在某些上下文中将
x op= y
计算为x = (T)(x op y)
。 存在这样的规则: 当左操作数是sbyte
,byte
,short
,ushort
或char
类型时 ,预定义运算符可以用作复合运算符 。 即使两个参数都属于这些类型之一,预定义运算符也会生成int类型的结果,如第12.4.7.3节中所述。 因此,如果没有强制转换,则无法将结果分配给左操作数 。对于预定义的运算符规则的直观的效果仅仅是
x op= y
是如果同时满足允许的x op y
和x = y
是允许的 。byte b = 0; char ch = '\\0'; int i = 0; b += 1; // Ok b += 1000; // Error, b = 1000 not permitted b += i; // Error, b = i not permitted b += (byte)i; // Ok ch += 1; // Error, ch = 1 not permitted ch += (char)1; // Ok
每个错误的直观原因是相应的简单分配也是一个错误。
简而言之,计算机说没有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.