C#閉パッケージオブジェクト


筆記試験の問題:

            List lists = new List();
            for (int i = 0; i < 5; i++)
            {
                Action act = () =>
                {
                    Console.WriteLine(i.ToString());
                };
                lists.Add(act);
            }


            foreach (var item in lists)
            {
                item();
            }

出力結果:5 5 5 5 5 5は分からないのではないでしょうか.この変数iは、ここではローカル変数だけでなく、actionの後に使用される変数であるため、コンテキストに関連する変数であり、宣言周期が向上するため、コンパイラは閉じたオブジェクトになり、iの値は5になります.正しい書き方は以下の通りです.
            List lists = new List();
            for (int i = 0; i < 5; i++)
            {
                int temp = i;
                Action t = () =>
                {
                    Console.WriteLine(temp.ToString());
                };
                lists.Add(t);
            }
            foreach (Action t in lists)
            {
                t();
            }

コンピュータでは、クローズド・パッケージ(Closure)は語法クローズド・パッケージ(Lexical Closure)の略称であり、自由変数を引用した関数である.この参照される自由変数はこの関数とともに存在し,それを創造する環境を離れても例外ではない.したがって,閉パケットは関数とそれに関連する参照環境とを組み合わせたエンティティであると考えられる.
1つの閉パケットは、生成された環境で、属する変数の範囲内で参照されるすべての変数をキャプチャまたは携帯する関数です.
var x = 1;
Action action = () =>
{
    var y = 2;
    var result = x+y;
    Console.Out.WriteLine("result = {0}", result);
};
action();

匿名関数(lambda式)を定義してタイプActionに割り当てます.actionの定義を観察すると、x変数を使用していることがわかります.ここで変数はactionによってキャプチャまたは携帯され,actionの実行環境に自動的に追加される.
閉パッケージとは、実際に使用される変数がその役割ドメインから離れているが、役割ドメインとコンテキスト関係があるため、現在の環境で上記の環境で定義された関数オブジェクトを引き続き使用することができる.