ループ内で変数の宣言をすると遅くなる?

2019年6月16日

変数の宣言場所の違い

変数iの宣言に注目して、次の2つのコードを比べてください。

コード自体には意味がありません。

サンプルコード1 変数の宣言をループ内に記述

while(true)
{
    int  i = 0;
    Console.WriteLine(i);
}
// whileループの外では、変数iは使わないとする

サンプルコード2 変数の宣言をループの外に記述

int  i;
while(true)
{
    i = 0;
    Console.WriteLine(i);
}
// whileループの外では、変数iは使わないとする

さて、どうでしょう?
コード1は、

  • ループ内で毎回宣言をしているので、速度が遅くなる。
  • 宣言は1度でいいので、ループ内に記述するのは良くない。
  • 宣言するたびにメモリがどんどん減っていくのでは?

と思われたのではないでしょうか?
でも、コード1は、次のようにも考えられます。

  • 変数の宣言と使用場所が近いため、わかりやすい。

また、コード2は、

  • コード行が多くなった場合に宣言と使用場所が離れることが考えられ、コードが追い辛く見にくい。

と言えます。

では、実行速度面では、どうでしょうか?

次の中間コード(IL)を見てみましょう。

実行コード

サンプルコード1のIL

        IL_0000: nop
        // sequence point: hidden
        IL_0001: br.s IL_000e
        // loop start (head: IL_000e)
            IL_0003: nop
            IL_0004: ldc.i4.1
            IL_0005: stloc.0
            IL_0006: ldloc.0
            IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
            IL_000c: nop
            IL_000d: nop

            IL_000e: ldc.i4.1
            IL_000f: stloc.1
            IL_0010: br.s IL_0003
        // end loop

サンプルコード2のIL

        IL_0000: nop
        // sequence point: hidden
        IL_0001: br.s IL_000e
        // loop start (head: IL_000e)
            IL_0003: nop
            IL_0004: ldc.i4.1
            IL_0005: stloc.0
            IL_0006: ldloc.0
            IL_0007: call void [mscorlib]System.Console::WriteLine(int32)
            IL_000c: nop
            IL_000d: nop

            IL_000e: ldc.i4.1
            IL_000f: stloc.1
            IL_0010: br.s IL_0003
        // end loop

検証結果

サンプルコード1とサンプルコード2で実行時点での違いはないことがわかりました。

なので、美しい書き方であるサンプルコード1に軍配が上がります。
昔のプログラム言語では、プログラムの先頭に変数の宣言をまとめて書くことが定石とされてきました。それはコンパイラがメモリの配置を効率よく行えるようにするためのもので、そうしないとエラーになりました。しかし、現在は、変数は可能な限り使用箇所の近くで宣言されているコードが読みやすく優れたコードとされています。
変数の有効範囲をできるだけ狭くすることで、変数の寿命を短くすることができます。

変数は使用場所に近いところで宣言するように!

C#

Posted by hidepon