My problem is hard to explain, so I created an example to show here.
When the WPF window in the example below is shown, three buttons are displayed, each one with a different text.
When anyone of these buttons is clicked, I assume its text should be displayed in the message, but instead, all of them display the same message, as if all of them were using the event handler of the last button.
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); } } }
Does anyone know what is wrong?
It is because of how closures are evaluated compiler in the loop:
The compiler assumes that you will need the context of
ain the closure, since you are usinga.Value, so it is creating one lambda expression that uses the value ofa. However,ahas scope across the entire loop, so it will simply have the last value assigned to it.To get around this, you need to copy
ato a variable inside the loop and then use that: