如何删除一个lambda事件处理程序
可能重复:
在C#中取消订阅匿名方法
我如何取消注册'匿名'事件处理程序
我最近发现我可以使用lambda来创建简单的事件处理程序。 我可以例如订阅像这样的点击事件:
button.Click += (s, e) => MessageBox.Show("Woho");
但是,你会如何取消订阅?
C#规范明确指出(IIRC)如果您有两个匿名函数(匿名方法或lambda表达式),它可能会或可能不会从该代码创建相同的委托。 (如果两个代表具有相同的目标并提及相同的方法,那么这两个代表是平等的。)
可以肯定的是,您需要记住您使用的委托实例:
EventHandler handler = (s, e) => MessageBox.Show("Woho");
button.Click += handler;
...
button.Click -= handler;
(我找不到规范的相关部分,但是我很惊讶地看到C#编译器积极尝试创建平等的代理,依靠它肯定是不明智的。)
如果你不想这样做,你需要提取一个方法:
public void ShowWoho(object sender, EventArgs e)
{
MessageBox.Show("Woho");
}
...
button.Click += ShowWoho;
...
button.Click -= ShowWoho;
如果你想创建一个使用lambda表达式来移除自己的事件处理程序,它有点棘手 - 你需要在lambda表达式本身中引用委托,并且你不能通过简单的“声明局部变量并赋值使用lambda表达式“,因为这个变量没有明确的赋值。 您通常通过首先为变量分配一个空值来解决这个问题:
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
实现会很棘手,因为您必须创建一个新的EventHandler
(它只是一个泛型类型参数)。 可以,但是很混乱。