ホームページ  >  記事  >  バックエンド開発  >  foreach ループ内のすべてのラムダ式が、個々の値ではなく同じ変数をキャプチャするのはなぜですか?

foreach ループ内のすべてのラムダ式が、個々の値ではなく同じ変数をキャプチャするのはなぜですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-10-28 22:16:30366ブラウズ

Why do all lambda expressions in a foreach loop capture the same variable instead of their individual values?

ラムダ式でキャプチャされた変数: 「foreach ループ変数」の謎を解き明かす

リストを作成することを目的とした以下の複雑なコードを考えてみましょう。さまざまなデータ型を認識するメソッドの例:

public class MyClass
{
    public delegate string PrintHelloType(string greeting);

    public void Execute()
    {
        Type[] types = new Type[]{typeof(string), typeof(float), typeof(int)};
        List<PrintHelloType> helloMethods = new List<PrintHelloType>();

        foreach (var type in types) {
            var sayHello = new PrintHelloType(greeting => SayGreetingToType(type, greeting));
            helloMethods.Add(sayHello);
        }

        foreach (var helloMethod in helloMethods) {
            Console.WriteLine(helloMethod("Hi"));
        }
    }

    public string SayGreetingToType(Type type, string greetingText) {
        return greetingText + " " + type.Name;
    }
}

ただし、このコードを実行すると、予期しない結果が発生します。意図した "Hi String"、"Hi" の代わりに、"Hi Int32" が 3 回出力されます。シングル」、「Hi Int32」。ここで何が起こっているのでしょうか?

クロージャとキャプチャされた変数の微妙さ

この動作を理解する鍵は、クロージャとキャプチャされた変数の概念にあります。ラムダ式が作成されると、周囲のスコープから変数がキャプチャされます。この場合、ラムダ式は f​​oreach ループから型変数をキャプチャします。

キャプチャされたループ変数: 落とし穴

重要なことに、キャプチャされた変数は次の値ではありません。型ではなく、変数そのものです。ループが進行するにつれて、型変数が変更されますが、ラムダ式は引き続き同じキャプチャされた変数を参照します。

問題の修正

意図した動作を実現するには、意図した値を取得するには、ループ内に新しい変数を作成する必要があります。コードを変更する方法は次のとおりです。

foreach (var type in types) {
   var newType = type;
   var sayHello = new PrintHelloType(greeting => SayGreetingToType(newType, greeting));
   helloMethods.Add(sayHello);
}

型の代わりに newType をキャプチャすることにより、ラムダ式は意図した値への定数参照を持つようになり、期待される出力が取得されます。

結論

ラムダ式を操作する場合、クロージャとキャプチャされた変数の複雑さを理解することが不可欠です。これらの仕組みに留意することで、予期しない動作を回避し、コードが意図したとおりに動作するようにすることができます。

以上がforeach ループ内のすべてのラムダ式が、個々の値ではなく同じ変数をキャプチャするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。