Dynamically Generating Buttons that Call a Lambda Function -- Variable Scope
I have a situation where I have someFunction(int)
, and I need to generate p开发者_如何转开发rogrammatically n
buttons that will call it. What this means is that I want to create buttons B1
, B2
, ... Bn
that call someFunction(1)
, someFunction(2)
, ... someFunction(n)
when clicked.
This is how I attempted to do this (semi-pseudocode):
for (int i = 1; i <= n; i++) {
Button b = new Button();
b.Caption = "Value " + n; // non-WPF: b.Text = "Value " + n;
b.Click += (sender, event) => {
someFunction(i);
}
}
What bugs me about this is that when I click on the first button (B1), with a debugger over someFunction(i)
, it tells me that it's calling someFunction(n + 1)
.
I'm not sure why this is, or how to fix it. The work-around I use is to use, instead of someFunction(i)
, someFunction(int.Parse(i.ToString())
(to create a copy of i
). But this seems shady to me, because integers should be value types.
I believe you understand WHY this happens. The problem is it captures the variable i
itself, not its value. The workaround that seems better (without toString and int.parse) to me is to declare another local var that copies i
for (int i = 1; i <= n; i++) {
Button b = new Button();
b.Caption = "Value " + n; // non-WPF: b.Text = "Value " + n;
int locali = i;
b.Click += (sender, event) => {
someFunction(locali);
}
}
This way the captured variable will be locali
and it will remain the same across the loop.
Stormbreaker is correct, for more information see Eric Lippert's answer to this question
C# lambda, local variable value not taken when you think?
精彩评论