i = i ++不会增加i.为什么?

Arm*_*yan 31 c# increment

可能重复:
为什么会进入无限循环?

类似于i = i++C和C++中的未定义行为,因为标量对象的值在同一表达式中更改两次而没有插入序列点.

但是我认为这些表达式在C#或Java中具有明确定义的行为,因为AFAIK对参数的评估从左到右,并且全部都有序列点.

那就是说,我希望i = i++相当于i++.但事实并非如此.以下程序输出0.

using System;
class Program
{
    static void Main(string[] args)
    {
        int i = 0;
        i = i++;
        Console.WriteLine(i);
    }
}
Run Code Online (Sandbox Code Playgroud)

你能帮我理解为什么吗?

免责声明: 我完全清楚,无论是否定义了上述结构的行为,它们都是愚蠢,无用,不可读,不必要的,不应在代码中使用.我只是好奇.

Cod*_*aos 42

行为在C#中定义良好,评估顺序为:

  1. 左侧i被评估为变量i
  2. 右侧被评估为0,并且i递增(现在i==1)
  3. 执行赋值,它设置i为0.(现在i==0)

最终的结果是i==0.

通常,您首先创建一个表达式树.要评估它,首先评估左侧,然后评估右侧,最后评估根部的操作.递归地做.

  • 在Java中,如果你使`i`易变(在我的测试中通常在1亿次迭代中为65次),你偶尔可以从并行线程中观察值`1`. (3认同)
  • *post*-increment运算符`i ++`运算符被定义为递增`i`但返回之前的值.另一方面,*pre*-increment运算符`++ i`返回递增的值.`i ++`=>`temp = i; i = i + 1; return temp;`vs` ++ i` =>`i = i + 1; return i;` (3认同)
  • @Ab`i = ++ i`会导致`i`最终成为1.但我不确定你的工作是什么意思'work fine`,因为这个问题必须具备代码需要达到的特定目的. (2认同)

Mar*_*ell 19

后增量表达式的结果i++是原始值i.所以之后i++进行了评估(递增i),您指定的旧值i来...... i.

只是用

i++;
Run Code Online (Sandbox Code Playgroud)

;)

  • @Marc我发现表达式从左到右混淆的表达式.我更喜欢将表达式视为树,然后以递归方式进行求值.每个节点首先从左到右评估其参数,最后自行执行. (3认同)

小智 17

i = ++i是你在想这里做的事情的代码.i++实际上表现得有点不同.

随着i++,值i增加,但值i++不是新值i,它是先前的值.所以当你这样做时i = i++,你会说"增加值i,然后设置i为旧值".

  • 第一线; 只是`i ++;`将是"他正在寻找的代码" (5认同)
  • 我不认为他正在寻找任何代码,但他正在寻找对C#语言的更好理解.特别是在哪个顺序中发生副作用以及表达式中同一变量的多个赋值结果如何表现. (3认同)

Mar*_*all 5

好吧,必须在赋值之前评估右侧的表达式。现在,i++将计算为 的当前值i,而 i 的值随后将增加 1。但是,分配尚未执行,当它执行时,它将i使用 rhs 表达式计算的任何值覆盖(1)的当前值,在您的情况下为 0。

主要区别在于++i(pre-increment, 评估为递增值) 和, or post-increment, 评估为递增的当前值。i i++i

如果您++i改为使用,则右侧表达式的计算结果将为 1,从而导致 i == 1。