调用Func 时为什么会出错?

我在C#中有以下代码片段:

var actions = new List<Func>(); IEnumerable values = new List { 1, 2, 3 }; foreach (int value in values) { actions.Add(() => value * value); } foreach (var action in actions) { Console.WriteLine(action()); ; } Console.ReadLine(); 

它运行正常,但我没有得到我期望的结果。

实际结果

9,9,9

预期结果

1,4,9

为什么我没有得到我期望的结果?

您正在捕获lambda表达式中的循环变量,这意味着当最终调用委托时,它会看到循环变量的最终值。

简单修复:

 foreach (int value in values) { int copy = value; actions.Add(() => copy * copy); } 

这样,您就可以在循环的每次迭代中获得一个新的copy变量,因此每个委托表达式将捕获一个不同的变量,并且它们不会受到随时间变化的循环变量( value )的影响。

Eric Lippert在“关闭循环变量被认为有害” (以及第二部分 )中对此做了很好的解释。

基本上这是C#中的“陷阱”,几乎每个人都迟早会失败。

您需要捕获循环内的变量。 现在,您的延迟执行操作正在使用第一个foreach循环中的最后一个值。

 var actions = new List>(); IEnumerable values = new List { 1, 2, 3 }; foreach (int value in values) { var v = value; actions.Add(() => v * v); } foreach (var action in actions) { Console.WriteLine(action()); ; } Console.ReadLine(); 

注意var v = value; 线。