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

时间:2018-09-09 01:37:05

标签: c# casting

我们知道这两个加法语句是等效的,并且可以编译为相同的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,因此对于我们来说,似乎编译器添加了一个应该是显式的强制转换。但这不能在第二条语句中完成。

在我看来,这是矛盾的,因为我希望第一个语句与第二个语句等效,并且从不编译,所以为什么要编译?

注意:当需要从longint的显式强制转换时,不会编译此代码:

int x = 100;
long y = 200;

x += y;

1 个答案:

答案 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)相同,其中Tx的类型,除了x是   仅评估一次。

  •   
  • 否则,复合分配无效,并且发生绑定时间错误。
  •   
     

...

     

等等等等

     

...

     

以上第二条规则允许在特定情况下将x op= y评估为x = (T)(x op y) 。该规则存在,以便当左操作数为时,预定义运算符可以用作复合运算符   类型sbytebyteshortushortchar 的类型。即使两者   参数是这些类型之一,预定义的运算符会产生   如第12.4.7.3节所述,为int类型的结果。 因此,无需演员   不可能将结果分配给左操作数

     

该规则对预定义运算符的直观影响很简单   如果x op= yx 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
     

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

简而言之,计算机说不。