ラムダ式の反復変数の予期しない動作を理解する
開発者は最近、ラムダ式内でのループ反復変数の使用に関するコンパイラ警告に遭遇しました。これは、予期しないプログラムの動作につながる一般的な落とし穴を浮き彫りにしています。 なぜこれが起こるのかを見てみましょう。
次のコード例を考えてみましょう:
<code class="language-csharp">List<Action> actions = new List<Action>(); for (int i = 0; i < 10; i++) { actions.Add(() => Console.WriteLine(i)); } foreach (Action action in actions) { action(); }</code>
これにより、0 から 9 までの数字が順番に出力されると期待されるかもしれません。 代わりに、「10」を 10 回出力します。 これは、ラムダ式が反復ごとに の コピーi
をキャプチャしないためです。 代わりに、変数 への 参照i
をキャプチャします。 foreach
ループが実行されるまでに、ループは完了し、i
は最終値 10 を保持します。したがって、各ラムダ式はこの最終値を出力します。
この予期せぬ結果は、このコーディング パターンを避けることの重要性を強調しています。 コンパイラの警告は重要な安全策として機能します。 目的のシーケンシャル出力を実現するには、ループ内に新しい変数を作成し、それに反復変数の値を代入します。
<code class="language-csharp">List<Action> actions = new List<Action>(); for (int i = 0; i < 10; i++) { int j = i; // Capture a copy of i actions.Add(() => Console.WriteLine(j)); } foreach (Action action in actions) { action(); }</code>
この改訂されたコードは、各ラムダ式が値 j
の一意で独立したコピーをキャプチャするようになったため、0 から 9 を正しく出力します。 この簡単な変更により、期待どおりの一貫した動作が保証されます。
以上がラムダ式で反復変数を使用すると予期しない結果が生じるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。