Maison >développement back-end >C++ >Pourquoi une expression Lambda à l'intérieur d'une boucle Foreach capture-t-elle la dernière valeur de la variable de boucle ?
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!