为什么我的优化 IL 在 save 变量中存储相同的值两次?

Why does my optimised IL store the same value in the save variable twice?

源码是一个for循环如下:

public class ForLoop
{
    public static void Main()
    {
        var count = 0;

        for (var i = 0; i < 10; i = i++)
        {
            count++;
        }
    }
}

我编译它时启用了优化 (csc /o+ ForLoop.cs),但是 IL 有一个 dup,后面跟着两个 stloc.1 和一个 ldloc.1

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       22 (0x16)
  .maxstack  3
  .locals init (int32 V_0,
           int32 V_1)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldc.i4.0
  IL_0003:  stloc.1
  IL_0004:  br.s       IL_0010
  IL_0006:  ldloc.0
  IL_0007:  ldc.i4.1
  IL_0008:  add
  IL_0009:  stloc.0
  IL_000a:  ldloc.1
  IL_000b:  dup
  IL_000c:  ldc.i4.1
  IL_000d:  add
  IL_000e:  stloc.1
  IL_000f:  stloc.1
  IL_0010:  ldloc.1
  IL_0011:  ldc.i4.s   10
  IL_0013:  blt.s      IL_0006
  IL_0015:  ret
} // end of method ForLoop::Main

IL_000b 的指令在我的 for 循环中复制了 i 变量。然后它加 1,存储结果,所以堆栈上剩下的是我的 i 的原始值,预添加。然后,它再次 存储它并再次加载它。

这感觉不是最佳甚至不正确。

那么它为什么要这么做?

首先你要明白i++其实就是三个运算:

  1. 获取i

  2. 的值
  3. 将值加一并存储。

  4. 将新值推回i

其次,你的代码是错误的。您的循环有 i = i++(而不是通常的简单 i++),这就是为什么您会看到额外的两个分配。

您正在执行上述三个步骤,并存储 i++ 的结果,然后将其推回 i