外变量陷阱

Gil*_*lla 46 c# linq

外部变量陷阱究竟是什么?感谢C#中的解释和示例.

编辑:纳入Jon Skeet的diktat :)

Eric Lippert关于外部变量陷阱

dtb*_*dtb 65

当开发人员期望变量的值被lambda表达式或匿名委托捕获时,实际上变量被捕获时,就会出现"外部变量陷阱".

例:

var actions = new List<Action>();
for (var i = 0; i < 10; i++)
{
    actions.Add(() => Console.Write("{0} ", i));
}
foreach (var action in actions)
{
    action();
}
Run Code Online (Sandbox Code Playgroud)

可能的输出#1:

0 1 2 3 4 5 6 7 8 9
Run Code Online (Sandbox Code Playgroud)

可能的输出#2:

10 10 10 10 10 10 10 10 10 10
Run Code Online (Sandbox Code Playgroud)

如果你期望输出#1,你就陷入了外部变量陷阱.你得到输出#2.

固定:

声明要重复捕获的"内部变量"而不是仅捕获一次的"外部变量".

var actions = new List<Action>();
for (var i = 0; i < 10; i++)
{
    var j = i;
    actions.Add(() => Console.Write("{0} ", j));
}
foreach (var action in actions)
{
    action();
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅Eric Lippert的博客.

  • 鉴于这很可能成为公认的答案,您是否有机会在Eric Lippert的博文中添加链接?http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx (4认同)
  • 对"陷阱"这个词有趣的双关语:该变量被捕获(被困),你被一个问题所困(陷入一个陷阱) (2认同)

hei*_*erg 5

就像是

foreach (var s in strings)
    var x = results.Where(r => (r.Text).Contains(s));
Run Code Online (Sandbox Code Playgroud)

不会给出您期望的结果,因为“包含”不会为每次迭代执行。不过,将 s 分配给循环内的临时变量将解决此问题。