我有以下代码用于创建动态按钮但消息框总是显示8.当我点击button[0][4]
时,如何在示例4中显示它?我已经尝试过labda和delegate但是两个都返回8(text[i].Count
)。变量i
也发生了同样的事情。
它必须是非常简单的东西,但我无法找到它: - (。
private void Form1_Load(object sender, EventArgs e)
{
for(int i = 0; i < text.Count; i++) // text.Count is 3
{
for(int a = 0; a < text[i].Count; a++) // text[i].Count is 8
{
button[i][a].Location = new Point(230, 30 +22 *a);
button[i][a].Text = "Done" + i + " " + a;
button[i][a].Click += delegate { click(a); };
...
private void click(int a)
{
MessageBox.Show("" +a);
}
答案 0 :(得分:4)
你正在关闭闭包内的循环变量 当事件触发时,该变量始终等于最后一项。
相反,你需要在循环中声明单独的变量,因此每个lambda都将捕获它自己永远不会改变的变量。
答案 1 :(得分:2)
由于SLaks还没有给出一个例子......我会的。以下是您的问题的小型重新创建:
internal class Test
{
public EventHandler Click;
}
..然后主要方法:
var list = new List<Test>();
for (int i = 0; i < 6; i++)
{
Test t = new Test();
t.Click += delegate
{
click(a);
};
list.Add(t);
}
foreach (var t in list)
{
t.Click(null, null); // 6, 6, 6, 6, 6
}
您需要在循环内创建一个局部变量,因此每个闭包都有自己的副本:
var list = new List<Test>();
for (int i = 0; i < 6; i++)
{
int a = i; /* <--------------- THIS LINE HERE ------------------ */
Test t = new Test();
t.Click += delegate
{
click(a); // use the new variable here
};
list.Add(t);
}
foreach (var t in list)
{
t.Click(null, null); // 0, 1, 2, 3, 4, 5
}
产生正确的输出。