我在C#中有以下代码片段:
var actions = new List<Func<int>>();
IEnumerable<int> values = new List<int> { 1, 2, 3 };
foreach (int value in values)
{
actions.Add(() => value * value);
}
foreach (var action in actions)
{
Console.WriteLine(action()); ;
}
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
它运行正常,但我没有得到我期望的结果.
实际结果
9,9,9
预期结果
1,4,9
为什么我没有得到我期望的结果?
Eni*_*ity 13
您需要捕获循环内的变量.现在,您的延迟执行操作正在使用value第一个foreach循环中的最后一个值.
var actions = new List<Func<int>>();
IEnumerable<int> values = new List<int> { 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();
Run Code Online (Sandbox Code Playgroud)
注意这一var v = value;行.
Jon*_*eet 12
您正在捕获lambda表达式中的循环变量,这意味着当最终调用委托时,它会看到循环变量的最终值.
简单修复:
foreach (int value in values)
{
int copy = value;
actions.Add(() => copy * copy);
}
Run Code Online (Sandbox Code Playgroud)
这样您就可以copy在循环的每次迭代中获得一个新变量,因此每个委托表达式将捕获一个不同的变量,并且它们不会受循环变量(value)随时间变化的影响.
Eric Lippert在"关闭循环变量被认为有害"(以及第二部分)中对此做了很好的解释.
基本上这是C#中的"陷阱",几乎每个人都迟早会失败.
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |