C# for vs. foreach Over An Array

This article coincides with this weblog entry and is intended to show the compiler differences between enumerating the elements in an Array using a manual for loop vs. using a foreach loop.

for approach

<codeSnippet language="C#">

    MyStruct[] myStructs = new MyStruct[3];


   for(int index = 0; index < myStructs.Length; index++)

    {

        Console.WriteLine("{0}", myStructs[index].MyField);

    }

</codeSnippet>
<codeSnippet language="CIL">
.method public hidebysig instance void  Test1() cil managed
{
  // Code size       55 (0x37)
  .maxstack  4
  .locals init (valuetype Test.Class1/MyStruct[] V_0,
           int32 V_1)
  IL_0000:  ldc.i4.3
  IL_0001:  newarr     Test.Class1/MyStruct
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.0
  IL_0008:  stloc.1
  IL_0009:  br.s       IL_0030
  IL_000b:  ldstr      "value of MyField for MyStruct at {0} is {1}"
  IL_0010:  ldloc.1
  IL_0011:  box        [mscorlib]System.Int32
  IL_0016:  ldloc.0
  IL_0017:  ldloc.1
  IL_0018:  ldelema    Test.Class1/MyStruct
  IL_001d:  ldfld      int32 Test.Class1/MyStruct::MyField
  IL_0022:  box        [mscorlib]System.Int32
  IL_0027:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object,
                                                                object)
  IL_002c:  ldloc.1
  IL_002d:  ldc.i4.1
  IL_002e:  add
  IL_002f:  stloc.1
  IL_0030:  ldloc.1
  IL_0031:  ldloc.0
  IL_0032:  ldlen
  IL_0033:  conv.i4
  IL_0034:  blt.s      IL_000b
  IL_0036:  ret
} // end of method Class1::Test1
</codeSnippet>

foreach approach

<codeSnippet language="C#">
    MyStruct[] myStructs = new MyStruct[3];
    foreach(MyStruct aStruct in myStructs)
    {
        Console.WriteLine("{0}", aStruct.MyField);
    }
</codeSnippet>
 
<codeSnippet language="CIL">
.method public hidebysig instance void  Test2() cil managed
{
  // Code size       59 (0x3b)
  .maxstack  2
  .locals init (valuetype Test.Class1/MyStruct[] V_0,
           valuetype Test.Class1/MyStruct V_1,
           valuetype Test.Class1/MyStruct[] V_2,
           int32 V_3)
  IL_0000:  ldc.i4.3
  IL_0001:  newarr     Test.Class1/MyStruct
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.2
  IL_0009:  ldc.i4.0
  IL_000a:  stloc.3
  IL_000b:  br.s       IL_0034
  IL_000d:  ldloc.2
  IL_000e:  ldloc.3
  IL_000f:  ldelema    Test.Class1/MyStruct
  IL_0014:  ldobj      Test.Class1/MyStruct
  IL_0019:  stloc.1
  IL_001a:  ldstr      "{1}"
  IL_001f:  ldloca.s   V_1
  IL_0021:  ldfld      int32 Test.Class1/MyStruct::MyField
  IL_0026:  box        [mscorlib]System.Int32
  IL_002b:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_0030:  ldloc.3
  IL_0031:  ldc.i4.1
  IL_0032:  add
  IL_0033:  stloc.3
  IL_0034:  ldloc.3
  IL_0035:  ldloc.2
  IL_0036:  ldlen
  IL_0037:  conv.i4
  IL_0038:  blt.s      IL_000d
  IL_003a:  ret
} // end of method Class1::Test2
</codeSnippet>