2010-12-02 13 views
1

私が実行した問題については説明できません。 foreachループでlambda構文を使用すると、forループで使用するよりも、基本的には別の答えが得られます。以下のコードでは、 "ディスパッチャ"クラスにデリゲートを登録します。私はその後、別の代理人の中に代議員をラップし、これらのラップされた代理人のリストを返します。私はそれらを実行します。ラップされた関数リストを実行すると予想される出力は1,2です。しかし、ラムダとforeachループを組み合わせると、私はそれを見ません。forループとforeachループ(クロージャ付き)で異なる動作

これは問題の原因となるコードではありませんが、問題を再現するための最も簡単なケースです。私はこれの使用事例について議論したくないと思うが、なぜ私が期待していない振る舞いをするのか、より興味がある。下のforeachループをラムダ構文で使用すると失敗します。新しいAction()構文を使用してforeachを使用すると、forループでラムダ構文を使用すると動作します。誰でもここで何が起こっているのか説明できますか?これは私が本当に困惑しています。

public class Holder 
{ 
    public Holder(int ID, Dispatcher disp) 
    { 
     this.ID = ID; 
     disp.Register(Something); 
    } 
    public int ID { get; set; } 
    private void Something(int test) { Console.WriteLine(ID.ToString()); } 
} 

public class Dispatcher 
{ 
    List<Action<int>> m_Holder = new List<Action<int>>(); 

    public void Register(Action<int> func) 
    { 
     m_Holder.Add(func); 
    } 

    public List<Action<int>> ReturnWrappedList() 
    { 
     List<Action<int>> temp = new List<Action<int>>(); 

     //for (int i = 0; i < m_Holder.Count; i++)  //Works - gives 1, 2 
     //{ 
     // var action = m_Holder[i]; 
     // temp.Add(p => action(p)); 
     //} 

     foreach (var action in m_Holder) 
     { 
      temp.Add(p => action(p)); //Fails - gives 2,2 
      //temp.Add(new Action<int>(action)); Works - gives 1,2 
     } 

     return temp; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var disp = new Dispatcher(); 
     var hold1 = new Holder(1, disp); 
     var hold2 = new Holder(2, disp); 
     disp.ReturnWrappedList().ForEach(p => p(1)); 
    } 
} 

答えて

4

これは、悪名高い "ループ変数をクローズする"というものです。

+0

おかげで、私はそれはコンパイラがforeachループをやっていた方法としなければならなかった考え出したが、私は問題だった正確に何を見つけ出すことができませんでした – Steve

0

あなたは試してみました:

foreach (var action in m_Holder) 
{ 
    var a = action; 
    temp.Add(p => a(p)); 
} 
0

をこれは、あなたが期待するものではありませんスコープで撮影したクロージャの古典的な問題です。 foreachでは、アクションは外側スコープを持っているため、実行はループのの最後のの値を取得します。 forの場合は、内側のスコープでアクションを作成するので、各反復でクロージャがローカル値を超えます。