首頁  >  文章  >  後端開發  >  為什麼 Foreach 迴圈內的 Lambda 表達式會捕捉循環變數的最後一個值?

為什麼 Foreach 迴圈內的 Lambda 表達式會捕捉循環變數的最後一個值?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-11-01 00:01:28338瀏覽

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

Foreach 循環中的Lambda 表達式失敗

考慮以下初始化委託列表的程式碼,每個委託都呼叫具有特定類型和問候語的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

但是,由於閉包行為,類型數組中的最後一個類型Int32 被所有lambda 捕獲表達式。因此,所有委託都以相同的類型呼叫SayGreetingToType,導致意外輸出:

Hi Int32
Hi Int32
Hi Int32

解決方案

要解決此問題,我們需要捕獲lambda 表達式中循環變數的值而不是變數本身:

<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>

此修改可確保每個lambda 表達式都有自己的類型副本,從而允許它使用正確的值呼叫SayGreetingToType輸入參數。

以上是為什麼 Foreach 迴圈內的 Lambda 表達式會捕捉循環變數的最後一個值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn