2010-11-24 12 views
0

次のプログラムこの場合、イベントの動作が異なるのはなぜですか?

static IEnumerable<Action> Create() 
{ 
    foreach (var i in Enumerable.Range(0, 2)) 
    { 
     yield return() => { Console.Write(i); }; 
    } 
} 

static void Main(string[] args) 
{ 
    foreach (var func in Create()) 
    { 
     func(); 
    } 

    Console.ReadLine(); 
} 

ouputs

このプログラム

static event Action SomethingHappened; 

static void Register() 
{ 
    foreach (var i in Enumerable.Range(0, 2)) 
    { 
     SomethingHappened +=() => { Console.Write(i); }; 
    } 
} 

static void Main(string[] args) 
{ 
    Register(); 
    SomethingHappened(); 
    Console.ReadLine(); 
} 

出力

なぜそうですか?プログラム2を出力するには01

答えて

3

ラムダ式でループ変数をキャプチャしています。これは、デリゲートが最終的に呼び出されたときに、それは変数の最新の値を使用することを意味...常に1はこれを試してみてくださいされる:

foreach (var i in Enumerable.Range(0, 2)) 
{ 
    int copy = i; 
    SomethingHappened +=() => { Console.Write(copy); }; 
} 

...それについてEric Lippert's blog postをお読みください。

1

第2のプログラムでは、変数iがラムダによって取り込まれます。正しい動作をさせるには、ラムダで使用する前にローカルコピーを作成します。例えば。

foreach (var i in Enumerable.Range(0, 2)) 
{ 
    var local = i; 
    SomethingHappened +=() => { Console.Write(local); }; 
} 
関連する問題