从这个答案https://stackoverflow.com/a/6457528/299110
我将ctrl.PreRender += (sender, e) => ControlPreRender(ctrl, rule);
用于foreach
中的一个或多个控件,每次都会更改ctrl和rule的值。
但是,当调用ControlPreRender
方法时,rule
参数似乎与附加事件处理程序的发件人不一致。
我知道我在这里遗漏了一些东西,但不确定是什么!
更新: 谢谢你的回答,Eric Lippert的博客真的解释了它。正如下选者所建议的那样,我已经将更多代码放在下面,希望稍微改善一下这个问题:
foreach (var ctrl in controls)
{
// ...
foreach (var rule in rules)
{
// ...
ctrl.PreRender += (sender, e) => ControlPreRender(ctrl, rule);
}
}
public static void ControlPreRender(Control ctrl, ControlRule rule)
{
// ...
}
答案 0 :(得分:3)
我想你想要一个临时变量:
foreach(var rule in rules)
{
var tmpRule = rule;
ctrl.PreRender += (sender, e) => ControlPreRender(sender as Control, tmpRule);
}
原因如下:如果没有该临时变量,所有匿名方法都会引用相同的实例,这会在您遍历所有规则时发生变化。这称为"access to modified closure"。正如erikkallen所提到的,这已在C#5中得到修复。
您可以轻松地自行检查:在ControlPreRender
和第一个断点点击make an object ID为规则参数设置断点。您将看到在断点的所有以下命中时,rule参数将具有相同的对象ID,这意味着它是完全相同的实例。
答案 1 :(得分:1)
Eric Lippert发布了two excellent blog posts的相关信息。您会注意到它们实际上对.NET 4.5进行了重大更改,以使foreach循环的行为与您预期的一样。 (Eric指的是C#5,令人困惑的是用于.NET 4.5的编译器版本。)Eric说,
“这是我们得到的最常见的错误错误报告。也就是说,有人认为他们在编译器中发现了一个错误,但事实上编译器是正确的。”
请注意@Daniel已经发布了正确的代码,根据Eric的帖子。