首页  >  文章  >  后端开发  >  为什么 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