首页 > 后端开发 > C++ > 为什么 Foreach 循环内的 Lambda 表达式会捕获循环变量的最后一个值?

为什么 Foreach 循环内的 Lambda 表达式会捕获循环变量的最后一个值?

Mary-Kate Olsen
发布: 2024-11-01 00:01:28
原创
469 人浏览过

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中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板