C#中的前后增量

Sch*_*der 61 c# pre-increment post-increment

我对C#编译器如何处理前后增量和减量有点困惑.

当我编写以下代码时:

int x = 4;
x = x++ + ++x;
Run Code Online (Sandbox Code Playgroud)

x之后会有10的价值.我认为这是因为预增量设置x5,这使得它的5+5 计算结果为10.然后后增量将更新x6,但不会使用此值,因为这10将被分配给x.

但是当我编码:

int x = 4;
x = x-- - --x;
Run Code Online (Sandbox Code Playgroud)

然后x将是2之后.任何人都可以解释为什么会这样吗?

Seb*_*Piu 50

x--将是4,但现在将是3 --x,所以它将结束为2,然后你将拥有

x = 4 - 2
Run Code Online (Sandbox Code Playgroud)

顺便说一下,你的第一个案例就是 x = 4 + 6

这是一个小例子,将打印出每个部分的值,也许这样你就会更好地理解它:

static void Main(string[] args)
{
    int x = 4;
    Console.WriteLine("x++: {0}", x++); //after this statement x = 5
    Console.WriteLine("++x: {0}", ++x); 

    int y = 4;
    Console.WriteLine("y--: {0}", y--); //after this statement y = 3
    Console.WriteLine("--y: {0}", --y);

    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

打印出来

x++: 4
++x: 6
y--: 4
--y: 2
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答 - 我认为在评估完整代码行之后/之前执行后增量和前增量 - 但是它们在表达式中每个项目的评估之后/之前执行. (3认同)
  • @Inuyasha:修正校正:在将变量评估为变量之后,运算符*始终*执行*.pre和post运算符之间的区别仅在于*返回的值*,而不是*执行操作的顺序*. (3认同)

Mon*_*ong 18

让我们看一下从该语句生成的IL

IL_0002:  ldloc.0     
Run Code Online (Sandbox Code Playgroud)

将x的值加载到堆栈上.堆栈=>(4)

IL_0003:  dup         
Run Code Online (Sandbox Code Playgroud)

复制堆栈中最顶层的项目.堆栈=>(4,4)

IL_0004:  ldc.i4.1    
Run Code Online (Sandbox Code Playgroud)

将1推入堆栈.堆栈=>(1,4,4)

IL_0005:  sub         
Run Code Online (Sandbox Code Playgroud)

减去两个顶部值并将结果推入堆栈.堆栈=>(3,4)

IL_0006:  stloc.0     
Run Code Online (Sandbox Code Playgroud)

将堆栈的最高值存储回x.堆栈=>(4)

IL_0007:  ldloc.0     
Run Code Online (Sandbox Code Playgroud)

将x的值加载回堆栈.堆栈=>(3,4)

IL_0008:  ldc.i4.1    
Run Code Online (Sandbox Code Playgroud)

将值1加载到堆栈上.堆栈=>(1,3,4)

IL_0009:  sub         
Run Code Online (Sandbox Code Playgroud)

减去这两个.堆栈=>(2,4)

IL_000A:  dup         
Run Code Online (Sandbox Code Playgroud)

重复顶部值=>(2,2,4)

IL_000B:  stloc.0     
Run Code Online (Sandbox Code Playgroud)

将最高值存储回x.堆栈=>(2,4)

IL_000C:  sub      
Run Code Online (Sandbox Code Playgroud)

减去两个最高值.堆栈=>(2)

IL_000D:  stloc.0  
Run Code Online (Sandbox Code Playgroud)

将此值存储回x.x == 2


Eri*_*ert 9

来自你的评论:

我认为在评估完整代码行之后/之前执行后增量和前增量 - 但是它们在表达式中每个项目的评估之后/之前执行.

你的误解是一个非常普遍的误解.请注意,在某些语言(如C)中,当副作用变得可见时未指定,因此在C中您的语句为真,因此它是合法的,但不是必需的.

在C#中并非如此; 在C#中,表达式左侧代码的副作用总是在右侧代码执行之前发生(来自单个线程;在多线程场景中,所有投注都关闭.)

有关增量运算符在C#中执行的操作的更详细说明,请参阅:

i ++和++ i有什么区别?

我在这个经常被误解的主题上撰写的文章还有很多其他链接.


Shy*_*mep 6

最有趣的是你会得到一个完全不同的答案用C++ .Net编译器.

int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1
Run Code Online (Sandbox Code Playgroud)

当然,结果的差异取决于不同的语义 - 看起来很正常.但是,尽管理解两个.net编译器对于这样的基本事物没有类似的行为这一事实也让我感到困惑.

  • 这与*parse*没有任何关系.它与两种语言关于序列点的不同允许语义有关. (4认同)
  • 在C++(不是Microsoft的C++非C++版本之一)中,在完整表达式结束之前多次修改变量会产生未定义的行为. (2认同)