Home > Backend Development > C++ > body text

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

Mary-Kate Olsen
Release: 2024-11-01 00:01:28
Original
407 people have browsed it

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

Failed Lambda Expression in Foreach Loop

Consider the following code that initializes a list of delegates, each of which calls a method SayGreetingToType with a specific type and greeting:

<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>
Copy after login

Upon executing this code, you would expect to see:

Hi String
Hi Single
Hi Int32
Copy after login

However, due to closure behavior, the last type in the types array, Int32, is captured by all lambda expressions. As a result, all delegates invoke SayGreetingToType with the same type, leading to the unexpected output of:

Hi Int32
Hi Int32
Hi Int32
Copy after login

The Solution

To resolve this issue, we need to capture the value of the loop variable within the lambda expression instead of the variable itself:

<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>
Copy after login

This modification ensures that each lambda expression has its own copy of the type, allowing it to invoke SayGreetingToType with the correct type argument.

The above is the detailed content of Why does a Lambda Expression inside a Foreach Loop capture the last value of the loop variable?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template