我的问题很难解释,所以我创建了一个示例在这里展示。
当显示下例中的 WPF 窗口时,会显示三个按钮,每个按钮都有不同的文本。
当单击这些按钮中的任何一个时,我认为其文本应该显示在消息中,但相反,所有这些按钮都显示相同的消息,就好像它们都使用最后一个按钮的事件处理程序一样。
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
var stackPanel = new StackPanel();
this.Content = stackPanel;
var n = new KeyValuePair<string, Action>[] {
new KeyValuePair<string, Action>("I", () => MessageBox.Show("I")),
new KeyValuePair<string, Action>("II", () => MessageBox.Show("II")),
new KeyValuePair<string, Action>("III", () => MessageBox.Show("III"))
};
foreach (var a in n) {
Button b = new Button();
b.Content = a.Key;
b.Click += (x, y) => a.Value();
stackPanel.Children.Add(b);
}
}
}
有人知道哪里出了问题吗?
最佳答案
这是因为编译器在循环中评估闭包的方式:
foreach (var a in n) {
Button b = new Button();
b.Content = a.Key;
b.Click += (x, y) => a.Value();
stackPanel.Children.Add(b);
}
编译器假定您在闭包中需要 a
的上下文,因为您使用的是 a.Value
,因此它会创建一个使用a
的值。但是,a
的作用域涵盖整个循环,因此它只会分配最后一个值。
要解决这个问题,您需要将 a
复制到循环内的变量,然后使用它:
foreach (var a in n) {
Button b = new Button();
b.Content = a.Key;
// Assign a to another reference.
var a2 = a;
// Set click handler with new reference.
b.Click += (x, y) => a2.Value();
stackPanel.Children.Add(b);
}
关于c# - 在 WPF 按钮单击事件上使用 lambda 表达式时出现奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/566687/