Search code examples
c#.netforeachil

Why IEnumerator.MoveNext is called before GetCurrent?


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?


Solution

  • 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()