动态对象

时间:2017-05-08 16:48:04

标签: c# events

我试图将EventHandler挂钩到动态创建的对象上。在此示例中,我使用简单的窗口.Net TabControl来包含动态对象。为简单起见,我使用Button及其Click事件。 重点是每个TabPage上的按钮点击应产生不同的输出

public partial class Form1 : Form
{
    int letter = 65;

    private void simpleButton1_Click(object sender, EventArgs e)
    {
        TabPage newPage = new TabPage();

        tabControl1.TabPages.Add(newPage);

        Button btn = new Button();

        newPage.Controls.Add(btn);

        btn.Click += (object s, EventArgs ee) =>
        {
            // Button on FirstPage should produce "Test A"
            // Button on SecondPage should produce "Test B"
            Debug.WriteLine("Test " + (char)letter);
        };

        letter++;
    }
}

但是,无论我在任何页面上点击哪个按钮都会产生最后一页的输出(即4个TabPages,所有按钮点击生成"测试D")。感觉就好像引用指针 Button btn 指向每个页面上的所有按钮实例。

我的假设:

Button btn = new Button();

每次执行此行时,指针btn是否指向Button的新实例?在那个意义上:

btn.Click += (object s, EventArgs ee) =>

btn.Click应该是新创建的Button实例的EventHandler,对吧?似乎指针btn仍然引用了Button的所有实例。

请在这件事上赐教。提前谢谢。

2 个答案:

答案 0 :(得分:1)

lambda表达式捕获对类中定义的letter字段的引用,因此该方法将始终使用存储在其中的最新值。

要在创建按钮时捕获letter的值,首先要创建一个局部变量来复制int值,然后捕获lambda表达式中的局部变量。

// Create a copy of the value
var character = (char)letter;

// Now the lambda will capture the local variable
btn.Click += (object s, EventArgs ee) =>
{
    Debug.WriteLine("Test " + character);
};

这对for loops的工作方式相同。

请参阅:

答案 1 :(得分:0)

变量只能包含一个值。

您有 N 个不同的按钮和 N 不同的事件处理程序。

但是,您只有一个letter字段,因此它们都做同样的事情。

相反,您可以在函数内部创建局部变量;然后,每个按钮将通过closures使用自己的变量。