Динамически генерируемые кнопки, которые вызывают лямбда-функцию - переменная область - PullRequest
3 голосов
/ 07 мая 2011

У меня есть ситуация, когда у меня есть someFunction(int), и мне нужно программно генерировать n кнопки, которые будут вызывать его.Это означает, что я хочу создать кнопки B1, B2, ... Bn, которые при нажатии вызывают someFunction(1), someFunction(2), ... someFunction(n).

ThisВот как я пытался сделать это (полупсевдокод):

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);
  }
}

Меня беспокоит то, что, когда я нажимаю на первую кнопку (B1) с отладчиком над someFunction(i),мне это звонит someFunction(n + 1).

Я не уверен, почему это так или как это исправить.Обходной путь, который я использую, должен использовать вместо someFunction(i), someFunction(int.Parse(i.ToString()) (для создания копии i).Но это кажется мне сомнительным, потому что целые числа должны быть типами значений.

Ответы [ 2 ]

2 голосов
/ 07 мая 2011

Полагаю, вы понимаете ПОЧЕМУ это происходит. Проблема в том, что он захватывает саму переменную i, а не ее значение. Обходной путь, который кажется мне лучше (без toString и int.parse), состоит в том, чтобы объявить другой локальный var, который копирует 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);
  }
}

Таким образом, захваченная переменная будет locali, и она останется неизменной в цикле.

1 голос
/ 07 мая 2011

Stormbreaker прав, для получения дополнительной информации см. Ответ Эрика Липперта на этот вопрос

C # лямбда, значение локальной переменной не принимается, когда вы думаете?

...