3

我将在 C# 中创建动态按钮,并且需要向 Click-Event-Handler (ID) 添加一个参数。

但是,在这个例子中,输出总是所有按钮的最后一个参数“10” ,而不是“1-2-3-4-5-....”,为什么?

for(int counter = 1; counter < 10; counter++)
{

    // Add new button

    Button btn = new Button();

    btn.Width = 250;
    btn.Height = 50;

    btn.Click += delegate (object sender1, EventArgs e1)
    { myEventHandler(sender1, e1, counter); };

    Test.Controls.Add(btn);

}


public void myEventHandler(object sender, EventArgs e, int i)
{

    MessageBox.Show("Test: " + i);

}

感谢您的帮助!

弗洛里安

4

2 回答 2

4

这是因为未捕获计数器变量。这意味着当循环完成时,计数器的值将是 10,因此所有委托都将具有该值来修复您可以在循环中使用如下变量:

for(int counter = 1; counter < 10; counter++)
{

    // Add new button

    Button btn = new Button();

    btn.Width = 250;
    btn.Height = 50;

    int num = counter;
    btn.Click += delegate (object sender1, EventArgs e1)
    { myEventHandler(sender1, e1, num ); };

    Test.Controls.Add(btn);

}


public void myEventHandler(object sender, EventArgs e, int i)
{

    MessageBox.Show("Test: " + i);

}

有关更多信息,请参阅 stackoverflow 上的此问题在 C# 循环中捕获的变量

于 2012-11-23T08:47:48.640 回答
2

那是因为委托捕获了变量的引用而不是。这意味着所有十个委托都包含对同一个变量的引用。执行委托后,此变量自然具有值 10,因为您的循环已经完成。countercounter

像这样修复它:

var tmp = counter;
btn.Click += delegate (object sender1, EventArgs e1)
{ myEventHandler(sender1, e1, tmp); };

现在每个委托都有自己的实例。

顺便说一句,您可以使用 lambda 语法使这段代码不那么冗长:

var tmp = counter;
btn.Click += (sender1, e1) => myEventHandler(sender1, e1, tmp);
于 2012-11-23T08:47:06.960 回答