混了这么久的C#,自以为对 Delegate 和 event 这样的基本概念已经了然于胸,却不曾想最近被一个这么基本特性给狠狠绊了一跤,实在是愧对天人,特此将这个问题暴露出来,警醒自己也提醒路人。
窗体的后台代码如下:
1 private void btnDelegateAdd1_Click(object sender, EventArgs e)
2 {
3 button1.Click += new EventHandler(button1_Click);
4 }
5
6 private void btnDelegateAdd2_Click(object sender, EventArgs e)
7 {
8 button2.Click += delegate
9 {
10 MessageBox.Show("我是按钮 2", "匿名方法");
11 };
12 }
13
14 private void button1_Click(object sender, EventArgs e)
15 {
16 MessageBox.Show("我是按钮 1", "普通方法");
17 }
2 {
3 button1.Click += new EventHandler(button1_Click);
4 }
5
6 private void btnDelegateAdd2_Click(object sender, EventArgs e)
7 {
8 button2.Click += delegate
9 {
10 MessageBox.Show("我是按钮 2", "匿名方法");
11 };
12 }
13
14 private void button1_Click(object sender, EventArgs e)
15 {
16 MessageBox.Show("我是按钮 1", "普通方法");
17 }
原本以为对同一个对象的同一事件进行同一方法的多次挂载(+=),不会造成该事件处理函数被重复加入到事件列表中,即如上代码,如果多次点击“添加Delegate”和“添加匿名Delegate”按钮后,不会在点击下面相应测试按钮时,导致多次执行。之所以有这种自以为,是觉得这样的重复加入没有意义,事件的add和remove内置方法会负责判断处理函数是否已在事件列表之中,却不曾想,这样的假设实在是越俎代庖。
如果不希望多次重复挂载事件处理的话,需要自己做出判断,譬如上面的btnDelegateAdd1按钮事件可以这么写:
1 private void btnDelegateAdd1_Click(object sender, EventArgs e)
2 {
3 button1.Click -= new EventHandler(button1_Click);
4 button1.Click += new EventHandler(button1_Click);
5 }
2 {
3 button1.Click -= new EventHandler(button1_Click);
4 button1.Click += new EventHandler(button1_Click);
5 }
但是,btnDelegateAdd2按钮事件中使用的是匿名方法,就没办法这样直接卸载事件处理函数了。