考虑以下代码:
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; } ... }
调用之后myClass.Execute(),代码将输出以下意外响应:
myClass.Execute()
嗨Int32 嗨Int32 嗨Int32
很显然,我希望"Hi String","Hi Single","Hi Int32",但显然并非如此。为什么在所有3种方法中都使用了迭代数组的最后一个元素而不是适当的方法?
"Hi String"
"Hi Single"
"Hi Int32"
您将如何重写代码以实现期望的目标?
欢迎来到闭包和捕获变量的世界:)
埃里克·利珀特(Eric Lippert)对这种行为有深入的解释:
基本上,捕获的是循环变量,而不是值。要获得您认为应该获得的东西,请执行以下操作:
foreach (var type in types) { var newType = type; var sayHello = new PrintHelloType(greeting => SayGreetingToType(newType, greeting)); helloMethods.Add(sayHello); }