转自 https://www.xuebuyuan.com/130945.html
发现程序的一个BUG究其原因是因为在for循环中用委托捕获了声明变量(就是那个常见的变量i),这种情况会发生在当你捕获了for循环的声明变量,但是在声明变量已经改变后才去调用委托,你期望得到捕获变量时的值,但是得到的会是变量最终的值,即便变量类型是值类型。来看这段代码:
var list = new Action[5];
for (int i = 0; i < 5; i++)
{
list[i] = new Action(() => Console.WriteLine(i));
}
foreach (var a in list)
a();
显然我期望每一个Action中捕获的是当时的值,但是输出会是:
5
5
5
5
5
for中的生命变量其实就是一个局部的全局变量,就类似这样:
int i = 0;
for (; i < 5; i++)
{ /* ... */ }
解决方案就是不用这个for循环的声明变量,可以随便声明一个局部临时变量来保存当前值:
for (; i < 5; i++)
{
var local = i;
list[i] = new Action(() => Console.WriteLine(local));
}
这样不不会输出5个5了。
当然用List.ForEach就不会出现这种问题,代码:
var list = new Action[5];
Enumerable.Range(0, 5).ToList().ForEach(i =>
{
list[i] = new Action(() => Console.WriteLine(i));
});
foreach (var a in list)
a();
输出:
0
1
2
3
4