源代码是一个 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
的指令复制了 my for 循环中的 i
变量。 然后它加 1,存储结果,所以堆栈上剩下的是我的原始值 i
,预加。 然后,它再次存储它,并再次加载它。
这感觉不是最佳的,甚至不正确。
那么它为什么要这样做呢?
,你必须明白i++
实际上是三个操作:
获取
i
的值向值添加 1 并存储它。
将新值推回
i
。
其次,你的代码是错误的。你的循环有i = i++
(而不是通常的简单i++
),这就是为什么你会看到额外的两个作业。
您正在执行提到的三个步骤,即存储i++
的结果,然后将其推送回i
。