gpt4 book ai didi

c# - LINQ、匿名类型和闭包的问题

转载 作者:行者123 更新时间:2023-11-30 14:03:47 24 4
gpt4 key购买 nike

我有一段代码使用 LINQ 过滤列表,创建匿名类型的实例列表,并为每个实例分配一个事件处理程序:

// 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 .

举个例子,如果我有两个菜单,“sin(x)”,槽位为 0 , 和 "cos(x)", 带插槽 1 , 两者 Click事件通过 1SetTrackedLine ,无论点击的是“sin(x)”还是“cos(x)”。

我的问题是,为什么会发生这种情况?不应该item.Slot引用匿名类型的每个单独实例?

谢谢。

最佳答案

你是closing over the loop variable .问题具体在这里:

(s, e) => graph.SetTrackedLine(item.Slot)
^^^^

使用的 item 的值将是 lambda 表达式运行时的当前值,而不是创建时的值.这是 C# 的“陷阱”和常见错误。

试试这个:

foreach (var item in items)
{
var item2 = item;
item2.Menu.Click += (s, e) => graph.SetTrackedLine(item2.Slot);
menuTrackLineWithMouse.DropDownItems.Add(item2.Menu);
}

关于c# - LINQ、匿名类型和闭包的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3465115/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com