只有当你需要这样做(本地分配)时,如果你在foreach循环或使用Linq。否则,您可能遇到修改关闭的问题。
以下是来自MSDN博客的摘录(以下所有内容均来自链接)。
http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx
但我自己走在前面。这个片段的输出是什么?
var values = new List<int>() { 100, 110, 120 };
var funcs = new List<Func<int>>();
foreach(var v in values)
funcs.Add(()=>v);
foreach(var f in funcs)
Console.WriteLine(f());
大多数人期望它是100/110/120。事实上,这是120元/ 120元/ 120为什么?因为()=> v表示“返回变量v的当前值”,而不是“创建委托时返回值v返回”。闭包关闭变量,而不是超过值。当这些方法运行时,显然分配给v的最后一个值是120,所以它仍然有这个值。
这很混乱。编写代码的正确方法是:
foreach(var v in values)
{
var v2 = v;
funcs.Add(()=>v2);
}
现在会发生什么情况?每次我们重新启动循环体时,我们都会在逻辑上创建一个新的变量v2。每个闭包在一个不同的v2上关闭,该v2只分配一次,因此它始终保持正确的值。
基本上,问题就出现了,因为我们指定foreach循环是
{
IEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator();
try
{
int m; // OUTSIDE THE ACTUAL LOOP
while(e.MoveNext())
{
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
一个语法糖如果我们指定的扩张是
try
{
while(e.MoveNext())
{
int m; // INSIDE
m = (int)(int)e.Current;
funcs.Add(()=>m);
}
那么代码会像预期的那样。
假设该变量没有在其他地方使用,我可以看到的第一种情况的唯一原因是帮助调试。 – ChrisF 2012-04-22 12:24:07