C# 动态生成调用Lambda函数的按钮——变量范围

C# 动态生成调用Lambda函数的按钮——变量范围,c#,delegates,parameter-passing,lambda,C#,Delegates,Parameter Passing,Lambda,在这种情况下,我有someFunction(int),我需要以编程方式生成调用它的n按钮。这意味着我要创建按钮B1,B2Bn调用someFunction(1),someFunction(2)某些函数(n)单击时 我就是这样尝试的(半伪代码): for(int i=1;i{ 功能(i); } } 这让我感到不舒服的是,当我点击第一个按钮(B1),调试器通过someFunction(I),它告诉我它正在调用someFunction(n+1) 我不知道这是为什么,也不知道如何解决。我使用的解决方法是

在这种情况下,我有
someFunction(int)
,我需要以编程方式生成调用它的
n
按钮。这意味着我要创建按钮
B1
B2
Bn
调用
someFunction(1)
someFunction(2)
<代码>某些函数(n)单击时

我就是这样尝试的(半伪代码):

for(int i=1;i{
功能(i);
}
}
这让我感到不舒服的是,当我点击第一个按钮(B1),调试器通过
someFunction(I)
,它告诉我它正在调用
someFunction(n+1)


我不知道这是为什么,也不知道如何解决。我使用的解决方法是使用,而不是
someFunction(I)
someFunction(int.Parse(I.ToString())
(创建
I
的副本)。但这对我来说似乎不太清楚,因为整数应该是值类型。

我相信你理解为什么会发生这种情况。问题是它捕获变量
I
本身,而不是它的值。对我来说,更好的解决方法(没有toString和int.parse)是声明另一个复制
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);
  }
}
for(int i=1;i{
someFunction(locali);
}
}

这样,捕获的变量将是
locali
,并且在整个循环中保持不变。

风暴断路器是正确的,有关更多信息,请参阅Eric Lippert对该问题的回答


这在精神上是正确的,但是
locali
应该在委托之外,而不是内部。@JSBangs为什么要在委托之外声明它?范围仅限于委托调用。@JSBangs您完全正确。我想我在将它放在其他代码之间时没有太多注意。@ashes999它应该在外部,因为如果它在内部学员的
i
仍将被捕获,最终结果将是相同的。尽管我非常喜欢此解决方案,但这似乎是一种黑客/诡计/变通方法,而不是一种合适的解决方案。是否有更好的方法来实现此目的?(如果这是唯一的答案并且有效,我会接受。)你可以阅读这篇文章。这篇文章是针对VB的,但理论是一样的,它们的工作方式是一样的。局部变量方式也是microsoft解决问题的方法(意外行为)。编辑:另一个链接:你刚刚发现闭包是如何工作的!:-)可能的重复
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);
  }
}