Maison  >  Article  >  développement back-end  >  Pourquoi toutes les expressions lambda dans une boucle foreach capturent-elles la même variable au lieu de leurs valeurs individuelles ?

Pourquoi toutes les expressions lambda dans une boucle foreach capturent-elles la même variable au lieu de leurs valeurs individuelles ?

Patricia Arquette
Patricia Arquetteoriginal
2024-10-28 22:16:30445parcourir

Why do all lambda expressions in a foreach loop capture the same variable instead of their individual values?

Variables capturées dans les expressions Lambda : démystifier le mystère de la "variable de boucle foreach"

Considérez le code déroutant ci-dessous, qui vise à créer une liste de méthodes qui accueillent différents types de données :

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) {
            var sayHello = new PrintHelloType(greeting => SayGreetingToType(type, greeting));
            helloMethods.Add(sayHello);
        }

        foreach (var helloMethod in helloMethods) {
            Console.WriteLine(helloMethod("Hi"));
        }
    }

    public string SayGreetingToType(Type type, string greetingText) {
        return greetingText + " " + type.Name;
    }
}

Cependant, lorsque vous exécutez ce code, vous rencontrez un résultat inattendu : il imprime trois fois "Hi Int32", au lieu du "Hi String" prévu, "Hi Single", "Salut Int32". Que se passe-t-il ici ?

La subtilité des fermetures et des variables capturées

La clé pour comprendre ce comportement réside dans le concept de fermetures et de variables capturées. Lorsqu'une expression lambda est créée, elle capture les variables de sa portée environnante. Dans ce cas, l'expression lambda capture la variable de type de la boucle foreach.

Variables de boucle capturées : un piège

Essentiellement, la variable capturée n'est pas la valeur de type, mais la variable elle-même. Au fur et à mesure que la boucle progresse, la variable de type change, tandis que les expressions lambda font toujours référence à la même variable capturée.

Corriger le problème

Pour obtenir le comportement souhaité, il est nécessaire de créer une nouvelle variable dans la boucle pour capturer la valeur souhaitée. Voici comment modifier le code :

foreach (var type in types) {
   var newType = type;
   var sayHello = new PrintHelloType(greeting => SayGreetingToType(newType, greeting));
   helloMethods.Add(sayHello);
}

En capturant newType au lieu du type, les expressions lambda ont désormais une référence constante à la valeur souhaitée et le résultat attendu est obtenu.

Conclusion

Comprendre les subtilités des fermetures et des variables capturées est essentiel lorsque l'on travaille avec des expressions lambda. En étant attentif à ces mécanismes, vous pouvez éviter les comportements inattendus et garantir que votre code fonctionne comme prévu.

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