如何删除一个lambda事件处理程序

可能重复:
在C#中取消订阅匿名方法
我如何取消注册“匿名”事件处理程序

我最近发现我可以使用lambda来创build简单的事件处理程序。 我可以例如订阅像这样的点击事件:

button.Click += (s, e) => MessageBox.Show("Woho"); 

但是,你会如何取消订阅?

C#规范明确指出(IIRC)如果您有两个匿名函数(匿名方法或lambdaexpression式),它可能会或可能不会创build相同的委托代码。 (如果两个代表具有相同的目标并提及相同的方法,那么这两个代表是平等的。)

可以肯定的是,您需要记住您使用的委托实例:

 EventHandler handler = (s, e) => MessageBox.Show("Woho"); button.Click += handler; ... button.Click -= handler; 

(我找不到规范的相关部分,但是我很惊讶地看到C#编译器积极地尝试创build相同的委托,依靠它肯定是不明智的。)

如果你不想这样做,你需要提取一个方法:

 public void ShowWoho(object sender, EventArgs e) { MessageBox.Show("Woho"); } ... button.Click += ShowWoho; ... button.Click -= ShowWoho; 

如果你想创build一个使用lambdaexpression式去除自己的事件处理程序,那么它有点棘手 – 你需要在lambdaexpression式本身中引用委托,而你不能用一个简单的“声明局部variables并赋值使用lambdaexpression式“,因为这个variables没有明确的赋值。 您通常通过首先为variables分配一个空值来解决这个问题:

 EventHandler handler = null; handler = (sender, args) => { button.Click -= handler; // Unsubscribe // Add your one-time-only code here } button.Click += handler; 

不幸的是,将其封装到一个方法中并不容易,因为事件没有被清晰地表示出来。 最近你可能会是这样的:

 button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) => { // One-time code here }, handler => button.Click -= handler); 

即使在Delegates.AutoUnsubscribe实现会很棘手,因为您必须创build一个新的EventHandler (这将只是一个genericstypes参数)。 可以,但是凌乱。