猿问

为什么 x = x + 100 的处理方式与编译为相同 IL 的 x += 100 不同?

我们知道这两个加法语句是等价的,并且编译成相同的 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,因此看起来编译器添加了一个对我们来说应该是显式的强制转换。但它不能在第二个语句中做到这一点。


这对我来说似乎是矛盾的,因为我希望第一个语句等同于第二个并且永远不会编译,那么为什么它会编译呢?


注意:当需要从longto显式转换时,这不会编译int:


int x = 100;

long y = 200;


x += y;


胡子哥哥
浏览 265回答 1
1回答

慕森王

您确实需要查看规格以获取此类信息(并且很难理解措辞)。然而,直接从马嘴里12.18.3 复合赋值x op= y通过应用二元运算符重载决议(第 12.4.5 节)来处理表单的操作,就好像该操作是编写的 x op y.然后,如果所选运算符的返回类型可隐式转换为 的类型x,则运算的计算结果为x = x  op y,但 x 仅计算一次。否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为 的类型x,并且如果y可隐式转换x 为x = (T)(x op y),其中T是 的类型x,除了x只计算一次。否则,复合赋值无效,并发生绑定时错误。...等等等等等等...上面的第二条规则允许在某些情况下x op= y进行评估。规则存在,使得预定义的运算符可以当左操作数的类型的被用作化合物运营商,,,,或。即使两个参数都是其中一种类型,预定义的运算符也会产生 int 类型的结果,如 §12.4.7.3 中所述。因此,如果没有强制转换,就不可能将结果分配给左操作数。x = (T)(x op y) sbytebyteshortushortchar预定义运算符的规则的直观效果很简单,x op= y即如果x op y和x = y都允许,则允许。byte b = 0;char ch = '\0';int i = 0;b += 1; // Okb += 1000; // Error, b = 1000 not permittedb += i; // Error, b = i not permittedb += (byte)i; // Okch += 1; // Error, ch = 1 not permittedch += (char)1; // Ok每个错误的直观原因是相应的简单分配也将是一个错误。简而言之,计算机说不。
随时随地看视频慕课网APP
我要回答