为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
胡子哥哥 2022-01-09 15:18:49
我们知道这两个加法语句是等价的,并且编译成相同的 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;
查看完整描述

1 回答

?
慕森王

TA贡献1777条经验 获得超3个赞

您确实需要查看规格以获取此类信息(并且很难理解措辞)。然而,直接从马嘴里

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 yx = 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

每个错误的直观原因是相应的简单分配也将是一个错误。

简而言之,计算机说不。


查看完整回答
反对 回复 2022-01-09
  • 1 回答
  • 0 关注
  • 206 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信