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
(这只是一个泛型类型参数)。可行,但很混乱。