为什么x = x + 100的处理方式不同于x + = 100,它们编译为相同的IL?

Sel*_*enç 7 c# casting

我们知道这两个加法语句是等价的,并编译为相同的IL代码:

int x = 100;

x += 100;
x = x + 100;
Run Code Online (Sandbox Code Playgroud)

但是,当需要明确的演员表时我发现​​了一些奇怪的东西:

byte b = 100;

b += 200; // Compiles (1)
b = b + 200; // Cannot implicitly convert int to byte (2)
b = (byte) (b + 200); // Compiles (3)
Run Code Online (Sandbox Code Playgroud)

很明显,为什么第二个语句需要显式转换,因为加法的结果是整数.但对我来说奇怪的是第一个声明.它编译为与第三个语句完全相同的IL,因此看起来编译器为我们添加了一个应该是显式的强制转换.但它不能在第二个声明中这样做.

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

注:当从需要有明确的转换这并不编译longint:

int x = 100;
long y = 200;

x += y;
Run Code Online (Sandbox Code Playgroud)

AAA*_*ddd 5

你真的需要去了解这类信息的规格(并且很难理解这些措辞).但是,直接从马口

12.18.3复合赋值

x op= y通过应用二元运算符重载决策(第12.4.5节)来处理表单的操作,就像写入操作一样 x op y..

  • 如果所选运算符的返回类型可隐式转换为类型x,则将操作计算为x = x op y,但x仅计算一次.

  • 否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为类型x,并且if 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; // 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
Run Code Online (Sandbox Code Playgroud)

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

简而言之,计算机说没有.