我最近发现我可以使用 lambdas 来创建简单的事件处理程序。例如,我可以订阅这样的点击事件:
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(这将只是一个泛型类型参数)。可行,但混乱。
Delegates.AutoUnsubscribe
EventHandler