如何删除 lambda 事件处理程序
我最近发现我可以使用 lambda 来创建简单的事件处理程序。例如,我可以订阅这样的点击事件:
button.Click += (s, e) => MessageBox.Show("Woho");
但是如何取消订阅呢?
I recently discovered that I can use lambdas to create simple event handlers. I could for example subscribe to a click event like this:
button.Click += (s, e) => MessageBox.Show("Woho");
But how would you unsubscribe it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C# 规范明确指出 (IIRC),如果您有两个匿名函数(匿名方法或 lambda 表达式),它可能会也可能不会从该代码创建相等的委托。 (如果两个委托具有相同的目标并引用相同的方法,则它们是相等的。)
可以肯定的是,您需要记住您使用的委托实例:(
我找不到规范的相关部分,但我'看到 C# 编译器积极尝试创建相等的委托,我会感到非常惊讶。依赖它肯定是不明智的。)
如果您不想这样做,则需要提取一个方法:
如果您想这样做创建一个使用 lambda 表达式删除自身的事件处理程序,这有点棘手 - 您需要在 lambda 表达式本身中引用委托,并且您不能通过简单的“声明一个局部变量并使用lambda 表达式”,因为这样变量就没有被明确赋值。通常,您可以通过首先为变量分配 null 值来解决此问题:
不幸的是,将其封装到方法中并不容易,因为事件没有清晰地表示。最接近的情况可能是这样的:
即使在 Delegates.AutoUnsubscribe 中实现这一点也很棘手,因为您必须创建一个新的 EventHandler (这只是泛型类型参数)。可行,但很混乱。
The C# specification explicitly states (IIRC) that if you have two anonymous functions (anonymous methods or lambda expressions) it may or may not create equal delegates from that code. (Two delegates are equal if they have equal targets and refer to the same methods.)
To be sure, you'd need to remember the delegate instance you used:
(I can't find the relevant bit of the spec, but I'd be quite surprised to see the C# compiler aggressively try to create equal delegates. It would certainly be unwise to rely on it.)
If you don't want to do that, you'll need to extract a method:
If you want to create an event handler which removes itself using a lambda expression, it's slightly trickier - you need to refer to the delegate within the lambda expression itself, and you can't do that with a simple "declare a local variable and assign to it using a lambda expression" because then the variable isn't definitely assigned. You typically get around this by assigning a null value to the variable first:
Unfortunately it's not even easy to encapsulate this into a method, because events aren't cleanly represented. The closest you could come would be something like:
Even that would be tricky to implement within
Delegates.AutoUnsubscribe
because you'd have to create a newEventHandler
(which would be just a generic type argument). Doable, but messy.