C# delegateとループ変数

delegateからループ変数のアクセスには注意がいる

以下のプログラムは"0"から"4"までの変数の出力させる事を意図して書いたが
実際に出力されるのは"5"が5回だ

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (Action actor in GenActors())
            {
                actor();
            }
            Console.ReadLine();
        }

        static List<Action> GenActors()
        {
            List<Action> result = new List<Action>();
            for (int i = 0; i < 5; ++i)
            {
                result.Add(delegate() { Console.WriteLine(i); });
            }
            return result;
        }
    }
}
5
5
5
5
5

しかし以下のようにループ変数を別の変数に入れ替えるとうまく動作する

        static List<Action> GenActors()
        {
            List<Action> result = new List<Action>();
            for (int i = 0; i < 5; ++i)
            {
                int j = i;
                result.Add(delegate() { Console.WriteLine(j); });
            }
            return result;
        }
0
1
2
3
4

ちなみにyield returnにしてもうまくいく

        static IEnumerable<Action> GenActors()
        {
            for (int i = 0; i < 5; ++i)
            {
                yield return delegate() { Console.WriteLine(i); };
            }
        }
0
1
2
3
4

ということで内部delegate使うときは
うまく変数をバインドしてるかテストしてみてね