我们知道这两个加法语句是等效的,并且可以编译为相同的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;
答案 0 :(得分:5)
您确实需要访问specs,以获取此类信息(而且很难理解措辞)。但是,直接从马口进来
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
评估为x = (T)(x op y)
。该规则存在,以便当左操作数为时,预定义运算符可以用作复合运算符 类型sbyte
,byte
,short
,ushort
或char
的类型。即使两者 参数是这些类型之一,预定义的运算符会产生 如第12.4.7.3节所述,为int类型的结果。 因此,无需演员 不可能将结果分配给左操作数。该规则对预定义运算符的直观影响很简单 如果
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
每个错误的直观原因是相应的简单 分配也将是一个错误。
简而言之,计算机说不。