事件处理程序与委托

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

}

感谢您的帮助! Florian
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);

}

有关C#中循环中的捕获变量的更多信息,请参见stackoverflow上的此问题Captured variable in a loop in C#


2

这是因为委托捕获了counter变量的引用而不是。这意味着所有十个委托都包含对同一个counter变量的引用。在执行委托时,这个变量自然具有值10,因为循环已经结束。

像这样修复它:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接