简体   繁体   English

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

[英]Why is x = x + 100 treated differently than x += 100 that compiles to the same IL?

We know that these two addition statements are equivalent and compile to the same IL code: 我们知道这两个加法语句是等价的,并编译为相同的IL代码:

int x = 100;

x += 100;
x = x + 100;

However, when there is an explicit cast required I have noticed something strange: 但是,当需要明确的演员表时我发现​​了一些奇怪的东西:

byte b = 100;

b += 200; // Compiles (1)
b = b + 200; // Cannot implicitly convert int to byte (2)
b = (byte) (b + 200); // Compiles (3)

It is obvious why the second statement requires an explicit cast because the result of the addition is an integer. 很明显,为什么第二个语句需要显式转换,因为加法的结果是整数。 But the weird thing to me is the first statement. 但对我来说奇怪的是第一个声明。 It compiles to the exact same IL as the third statement, so it looks like compiler adds a cast that is supposed to be explicit, for us. 它编译为与第三个语句完全相同的IL,因此看起来编译器为我们添加了一个应该是显式的强制转换。 But it can't do it in the second statement. 但它不能在第二个声明中这样做。

It seems contradictory to me because I would expect the first statement to be equivalent to the second and never compile, so why does it compile? 这对我来说似乎是矛盾的,因为我希望第一个语句等同于第二个语句并且永远不会编译,所以它为什么要编译?

Note: This doesn't compile when an explicit cast is required from long to int : 注意:当从longint需要显式强制转换时,这不会编译:

int x = 100;
long y = 200;

x += y;

You really need to go to the specs for this sort of information (and it can be really hard to get your head around the wording). 你真的需要去了解这类信息的规格 (并且很难理解这些措辞)。 However, straight from the horses mouth 但是,直接从马口

12.18.3 Compound assignment 12.18.3复合赋值

An operation of the form x op= y is processed by applying binary operator overload resolution (§12.4.5) as if the operation was written x op y. x op= y形式的x op= y通过应用二元运算符重载决策(第12.4.5节)来处理,就好像操作是在x op y.中编写的一样x op y. Then, 然后,

  • If the return type of the selected operator is implicitly convertible to the type of x , the operation is evaluated as x = x op y , except that x is evaluated only once. 如果所选运算符的返回类型可隐式转换为x的类型,则操作将计算为x = x op y ,但x仅计算一次。

  • Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x , and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y) , where T is the type of x , except that x is evaluated only once. 否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为x类型,并且如果y可隐式转换为x类型或运算符是移位运算符,则操作被评估为x = (T)(x op y) ,其中Tx的类型,除了x仅被计算一次。

  • Otherwise, the compound assignment is invalid, and a binding-time error occurs. 否则,复合赋值无效,并发生绑定时错误。

... ...

blah blah blah 等等等等等等

... ...

The second rule above permits x op= y to be evaluated as x = (T)(x op y) in certain contexts . 上面的第二条规则允许在某些上下文中将 x op= y计算为x = (T)(x op y) The rule exists such that the predefined operators can be used as compound operators when the left operand is of type sbyte , byte , short , ushort , or char . 存在这样的规则: 当左操作数是sbytebyteshortushortchar类型时 ,预定义运算符可以用作复合运算符 Even when both arguments are of one of those types, the predefined operators produce a result of type int, as described in §12.4.7.3. 即使两个参数都属于这些类型之一,预定义运算符也会生成int类型的结果,如第12.4.7.3节中所述。 Thus, without a cast it would not be possible to assign the result to the left operand . 因此,如果没有强制转换,则无法将结果分配给左操作数

The intuitive effect of the rule for predefined operators is simply that x op= y is permitted if both of x op y and x = y are permitted . 对于预定义的运算符规则的直观的效果仅仅是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 

the intuitive reason for each error is that a corresponding simple assignment would also have been an error. 每个错误的直观原因是相应的简单分配也是一个错误。

In short, computer says no. 简而言之,计算机说没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM