ホームページ  >  記事  >  バックエンド開発  >  Foreach ループ内のラムダ式がループ変数の最後の値をキャプチャするのはなぜですか?

Foreach ループ内のラムダ式がループ変数の最後の値をキャプチャするのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-01 00:01:28339ブラウズ

Why does a Lambda Expression inside a Foreach Loop capture the last value of the loop variable?

Foreach ループでのラムダ式の失敗

デリゲートのリストを初期化する次のコードを考えます。各デリゲートは、特定の種類と挨拶を指定してメソッド SayGreetingToType を呼び出します。

<code class="csharp">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)
        {
            // Initialize the lambda expression with the captured variable 'type'
            var sayHello = new PrintHelloType(greeting => SayGreetingToType(type, greeting));
            helloMethods.Add(sayHello);
        }

        // Call the delegates with the greeting "Hi"
        foreach (var helloMethod in helloMethods)
        {
            Console.WriteLine(helloMethod("Hi"));
        }
    }

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

このコードを実行すると、次の結果が表示されると予想されます。

Hi String
Hi Single
Hi Int32

ただし、クロージャーの動作により、types 配列の最後の型 Int32 はすべてのラムダによってキャプチャされます。表現。その結果、すべてのデリゲートが同じ型で SayGreetingToType を呼び出し、次のような予期しない出力が発生します。

Hi Int32
Hi Int32
Hi Int32

解決策

この問題を解決するには、次のことが必要です。変数自体ではなくラムダ式内のループ変数の値をキャプチャするには:

<code class="csharp">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)
        {
            // Capture a copy of the current 'type' value using a new variable
            var newType = type;

            // Initialize the lambda expression with the new variable 'newType'
            var sayHello = new PrintHelloType(greeting => SayGreetingToType(newType, greeting));
            helloMethods.Add(sayHello);
        }

        // Call the delegates with the greeting "Hi"
        foreach (var helloMethod in helloMethods)
        {
            Console.WriteLine(helloMethod("Hi"));
        }
    }

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

この変更により、各ラムダ式が型の独自のコピーを持つことが保証され、正しい値で SayGreetingToType を呼び出すことができるようになります。型引数。

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

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