我们知道这两个加法语句是等价的,并编译为相同的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,因此看起来编译器为我们添加了一个应该是显式的强制转换.但它不能在第二个声明中这样做.
这对我来说似乎是矛盾的,因为我希望第一个语句等同于第二个语句并且永远不会编译,所以它为什么要编译?
注:当从需要有明确的转换这并不编译long到int:
int x = 100;
long y = 200;
x += y;
Run Code Online (Sandbox Code Playgroud)
你真的需要去了解这类信息的规格(并且很难理解这些措辞).但是,直接从马口
12.18.3复合赋值
x op= y通过应用二元运算符重载决策(第12.4.5节)来处理表单的操作,就像写入操作一样x op y..
如果所选运算符的返回类型可隐式转换为类型
x,则将操作计算为x = x op y,但x仅计算一次.否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为类型
x,并且ify可隐式转换为类型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被允许.Run Code Online (Sandbox Code Playgroud)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每个错误的直观原因是相应的简单分配也是一个错误.
简而言之,计算机说没有.