为什么IEnumerator.在GetCurrent之前调用MoveNext

本文关键字:调用 MoveNext GetCurrent IEnumerator 为什么 | 更新日期: 2023-09-27 18:09:13

我是一个完全陌生的IL,但我知道MoveNext应该在Current之前调用,让我们说我们有这样的foreach语句:

foreach (var i in Enumerable.Empty<string>())
{          
}

如果我们查看生成的IL,我们会看到Current实际上首先被调用:

IL_0014:  br.s       IL_001f
IL_0016:  ldloc.1
IL_0017:  callvirt   instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<string>::get_Current()
IL_001c:  stloc.0
IL_001d:  nop
IL_001e:  nop
IL_001f:  ldloc.1
IL_0020:  callvirt   instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0025:  stloc.2
IL_0026:  ldloc.2
IL_0027:  brtrue.s   IL_0016
IL_0029:  leave.s    IL_003b

问题是为什么?

为什么IEnumerator.在GetCurrent之前调用MoveNext

IL_0014:  br.s       IL_001f

根据MSDN, br.s

无条件地将控制转移到目标指令(简称)。

引用的地址是调用MoveNext的指令。

IL_001f:  ldloc.1
IL_0020:  callvirt   instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()