I am completely new to IL, but as I know MoveNext
should be called before Current
, lets say we have such foreach statement:
foreach (var i in Enumerable.Empty<string>())
{
}
if we look at generated IL we will see that Current is actually called first:
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
The question is why?
IL_0014: br.s IL_001f
According to MSDN, br.s
Unconditionally transfers control to a target instruction (short form).
The referenced address is the instructions which call MoveNext
.
IL_001f: ldloc.1
IL_0020: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()