Maison  >  Article  >  développement back-end  >  Pourquoi une expression Lambda à l'intérieur d'une boucle Foreach capture-t-elle la dernière valeur de la variable de boucle ?

Pourquoi une expression Lambda à l'intérieur d'une boucle Foreach capture-t-elle la dernière valeur de la variable de boucle ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-01 00:01:28341parcourir

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

Échec de l'expression Lambda dans la boucle Foreach

Considérez le code suivant qui initialise une liste de délégués, dont chacun appelle une méthode SayGreetingToType avec un type et un message d'accueil spécifiques :

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

Lors de l'exécution de ce code, vous vous attendez à voir :

Hi String
Hi Single
Hi Int32

Cependant, en raison du comportement de fermeture, le dernier type du tableau types, Int32, est capturé par toutes les expressions lambda. En conséquence, tous les délégués invoquent SayGreetingToType avec le même type, ce qui entraîne le résultat inattendu de :

Hi Int32
Hi Int32
Hi Int32

La solution

Pour résoudre ce problème, nous avons besoin pour capturer la valeur de la variable de boucle dans l'expression lambda au lieu de la variable elle-même :

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

Cette modification garantit que chaque lambda L'expression a sa propre copie du type, lui permettant d'invoquer SayGreetingToType avec l'argument de type correct.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn