问题LINQ,匿名类型,和封闭 [英] Problem with LINQ, anonymous types, and closures
问题描述
我有一块能过滤使用LINQ列表代码,创建一个匿名类型的实例的列表,以及事件处理程序分配给每个实例
I have a piece of code that filters a list using LINQ, creates a list of instances of an anonymous type, and assigns an event handler to each instance:
// Select every linear expression and create a menu item from it
var items = from expr in expressionList.Expressions
where expr.Type == ExpressionType.Linear
let stdExpr = (StandardExpression)expr
select new
{
Menu = new ToolStripMenuItem(stdExpr.Expression), // string
stdExpr.Slot // int
};
// Wire a Click event handler to each menu to set the tracked line
foreach (var item in items)
{
item.Menu.Click += (s, e) => graph.SetTrackedLine(item.Slot);
menuTrackLineWithMouse.DropDownItems.Add(item.Menu);
}
这工作得很好,该事件处理程序获得有线和菜单得到正确添加。问题就来了被点击菜单项时,和处理程序被激发。不管是什么菜单项引发的处理程序,只有最后一个是不断传递给 SetTrackedLine
。
This works well in that the event handlers get wired and the menus get added correctly. The problem comes when the menu item is clicked, and the handler is fired. No matter what menu item fired the handler, only the last one is ever passed to SetTrackedLine
.
一个例子是如果我有两个菜单,罪(X),与插槽 0
和COS(X),与插槽 1
,无论点击
事件传递 1
到 SetTrackedLine
,不管罪(X)被点击或COS(X)了。
An example is if I have two menus, "sin(x)", with slot 0
, and "cos(x)", with slot 1
, both Click
events pass 1
to SetTrackedLine
, no matter if "sin(x)" was clicked or "cos(x)" was.
我的问题是,为什么会出现这种情况?不应该 item.Slot
引用匿名类型的每个单独的实例?
My question is, why does this happen? Shouldn't item.Slot
refer to each separate instance of the anonymous type?
感谢。
推荐答案
您是的关闭了循环变量。这个问题特别是在这里:
You are closing over the loop variable. The problem specifically is here:
(s, e) => graph.SetTrackedLine(item.Slot)
^^^^
<$的值C $ C>项目运行,而不是它有当它是值>的创建的的。这是一个C的疑难杂症#和一个常见的错误
The value of item
used will be the current value when the lambda expression is run, not the value it had when it was created. This is a "gotcha" of C# and a common error.
试试这个:
foreach (var item in items)
{
var item2 = item;
item2.Menu.Click += (s, e) => graph.SetTrackedLine(item2.Slot);
menuTrackLineWithMouse.DropDownItems.Add(item2.Menu);
}
这篇关于问题LINQ,匿名类型,和封闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!