ラムダ式は、ループ内でインライン関数を定義する簡潔な方法を提供します。ただし、反復変数をラムダで直接使用すると、後で予期しない動作が発生する可能性があります。
反復変数のラムダ トラップ:
次のコードを考えてみましょう:
<code class="language-c#">for (int i = 0; i < 10; i++) { Action action = () => Console.WriteLine(i); actions.Add(action); } foreach (var action in actions) { action(); }</code>
各ラムダが i の対応する値を出力すると考える人もいるかもしれません。ただし、クロージャにより、すべてのラムダは i への同じキャプチャされた参照を共有します。
予期しない印刷結果:
ループが終了すると、i は 10 になり、すべてのラムダはこの最終値を指すようになります。その結果、ラムダを実行すると、予期される 0 から 9 までのシーケンスではなく、「10」が 10 回出力されます。
この動作は、ループが完了した後でも、ラムダ クロージャがスコープ内で宣言された変数への参照を維持することに起因します。
回避策と代替案:
この問題を解決するには、ループ内にローカル変数を作成し、それに反復変数の値を割り当てます。
<code class="language-c#">for (int i = 0; i < 10; i++) { int j = i; // 创建一个局部变量 Action action = () => Console.WriteLine(j); actions.Add(action); } foreach (var action in actions) { action(); }</code>
これにより、各ラムダが j の異なる値を確実にキャプチャし、期待どおりの一連の出力が得られます。
ラムダ式で反復変数を直接使用すると、予期しないクロージャ関連の状況が発生する可能性があることに注意してください。代わりに、必要な値を正確に取得するローカル変数を作成することを検討してください。
以上がラムダ式が反復変数の最終値を取得するのはなぜですか?これを回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。