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