LoginSignup
2
1

More than 5 years have passed since last update.

C#のforeachの仕組み(5) ILにおけるforとの比較 int[]編

Posted at

C#のforeachの仕組み(4) ILにおけるforとの比較 の続きです。

概要

C#のforeachの仕組み(4) ILにおけるforとの比較@NetSeed からのコメントより。

T[]に対するfor/foreachもみてみると楽しいかも?

Let's try!

コードとIL

forのコード。

Implement_array_for
using System;

namespace ConsoleAppArrayFor
{
    class Program
    {
        static void Main()
        {
            int[] numbers = { 0, 1, 2, 3, 4, 5, 6 };

            for (int i = 0; i < numbers.Length; i++)
            {
                Console.WriteLine(numbers[i]);
            }
        }
    }
}

forのIL。

IL_array_for
.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // コード サイズ       49 (0x31)
  .maxstack  3
  .locals init (int32[] V_0,
           int32 V_1,
           bool V_2)
  IL_0000:  nop
  IL_0001:  ldc.i4.7
  IL_0002:  newarr     [System.Runtime]System.Int32
  IL_0007:  dup
  IL_0008:  ldtoken    field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=28' '<PrivateImplementationDetails>'::'50567A6578C37E24118E2B7EE8F5C7930666F62F'
  IL_000d:  call       void [System.Runtime]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [System.Runtime]System.Array,
                                                                                                            valuetype [System.Runtime]System.RuntimeFieldHandle)
  IL_0012:  stloc.0
  IL_0013:  ldc.i4.0
  IL_0014:  stloc.1
  IL_0015:  br.s       IL_0026
  IL_0017:  nop
  IL_0018:  ldloc.0
  IL_0019:  ldloc.1
  IL_001a:  ldelem.i4
  IL_001b:  call       void [System.Console]System.Console::WriteLine(int32)
  IL_0020:  nop
  IL_0021:  nop
  IL_0022:  ldloc.1
  IL_0023:  ldc.i4.1
  IL_0024:  add
  IL_0025:  stloc.1
  IL_0026:  ldloc.1
  IL_0027:  ldloc.0
  IL_0028:  ldlen
  IL_0029:  conv.i4
  IL_002a:  clt
  IL_002c:  stloc.2
  IL_002d:  ldloc.2
  IL_002e:  brtrue.s   IL_0017
  IL_0030:  ret
} // end of method Program::Main

foreachのコード。

Implement_array_foreach
using System;

namespace ConsoleAppArrayFor
{
    class Program
    {
        static void Main()
        {
            int[] numbers = { 0, 1, 2, 3, 4, 5, 6 };

            foreach (var n in numbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}

foreachのIL。

IL_array_foreach
.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // コード サイズ       50 (0x32)
  .maxstack  3
  .locals init (int32[] V_0,
           int32[] V_1,
           int32 V_2,
           int32 V_3)
  IL_0000:  nop
  IL_0001:  ldc.i4.7
  IL_0002:  newarr     [System.Runtime]System.Int32
  IL_0007:  dup
  IL_0008:  ldtoken    field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=28' '<PrivateImplementationDetails>'::'50567A6578C37E24118E2B7EE8F5C7930666F62F'
  IL_000d:  call       void [System.Runtime]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [System.Runtime]System.Array,
                                                                                                            valuetype [System.Runtime]System.RuntimeFieldHandle)
  IL_0012:  stloc.0
  IL_0013:  nop
  IL_0014:  ldloc.0
  IL_0015:  stloc.1
  IL_0016:  ldc.i4.0
  IL_0017:  stloc.2
  IL_0018:  br.s       IL_002b
  IL_001a:  ldloc.1
  IL_001b:  ldloc.2
  IL_001c:  ldelem.i4
  IL_001d:  stloc.3
  IL_001e:  nop
  IL_001f:  ldloc.3
  IL_0020:  call       void [System.Console]System.Console::WriteLine(int32)
  IL_0025:  nop
  IL_0026:  nop
  IL_0027:  ldloc.2
  IL_0028:  ldc.i4.1
  IL_0029:  add
  IL_002a:  stloc.2
  IL_002b:  ldloc.2
  IL_002c:  ldloc.1
  IL_002d:  ldlen
  IL_002e:  conv.i4
  IL_002f:  blt.s      IL_001a
  IL_0031:  ret
} // end of method Program::Main

ILの相違点

diff_for_foreach_IL
@@ -1,11 +1,12 @@
 .method private hidebysig static void  Main() cil managed
 {
   .entrypoint
-  // コード サイズ       49 (0x31)
+  // コード サイズ       50 (0x32)
   .maxstack  3
   .locals init (int32[] V_0,
-           int32 V_1,
-           bool V_2)
+           int32[] V_1,
+           int32 V_2,
+           int32 V_3)
   IL_0000:  nop
   IL_0001:  ldc.i4.7
   IL_0002:  newarr     [System.Runtime]System.Int32
@@ -14,28 +15,30 @@
   IL_000d:  call       void [System.Runtime]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [System.Runtime]System.Array,
                                                                                                             valuetype [System.Runtime]System.RuntimeFieldHandle)
   IL_0012:  stloc.0
-  IL_0013:  ldc.i4.0
-  IL_0014:  stloc.1
-  IL_0015:  br.s       IL_0026
-  IL_0017:  nop
-  IL_0018:  ldloc.0
-  IL_0019:  ldloc.1
-  IL_001a:  ldelem.i4
-  IL_001b:  call       void [System.Console]System.Console::WriteLine(int32)
-  IL_0020:  nop
-  IL_0021:  nop
-  IL_0022:  ldloc.1
-  IL_0023:  ldc.i4.1
-  IL_0024:  add
-  IL_0025:  stloc.1
-  IL_0026:  ldloc.1
-  IL_0027:  ldloc.0
-  IL_0028:  ldlen
-  IL_0029:  conv.i4
-  IL_002a:  clt
-  IL_002c:  stloc.2
-  IL_002d:  ldloc.2
-  IL_002e:  brtrue.s   IL_0017
-  IL_0030:  ret
+  IL_0013:  nop
+  IL_0014:  ldloc.0
+  IL_0015:  stloc.1
+  IL_0016:  ldc.i4.0
+  IL_0017:  stloc.2
+  IL_0018:  br.s       IL_002b
+  IL_001a:  ldloc.1
+  IL_001b:  ldloc.2
+  IL_001c:  ldelem.i4
+  IL_001d:  stloc.3
+  IL_001e:  nop
+  IL_001f:  ldloc.3
+  IL_0020:  call       void [System.Console]System.Console::WriteLine(int32)
+  IL_0025:  nop
+  IL_0026:  nop
+  IL_0027:  ldloc.2
+  IL_0028:  ldc.i4.1
+  IL_0029:  add
+  IL_002a:  stloc.2
+  IL_002b:  ldloc.2
+  IL_002c:  ldloc.1
+  IL_002d:  ldlen
+  IL_002e:  conv.i4
+  IL_002f:  blt.s      IL_001a
+  IL_0031:  ret
 } // end of method Program::Main

まとめ

  • foreachなのにGetEnumerator()もMoveNext()していない!
  • int32[] V_1でforしている?
  • foreachがforの糖衣構文みたいになっている?
  • ステップ数も少ないしT[]の方が早そう
2
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1