如何取消订阅使用 lambda 表达式的事件?
Posted
技术标签:
【中文标题】如何取消订阅使用 lambda 表达式的事件?【英文标题】:How to unsubscribe from an event which uses a lambda expression? 【发布时间】:2010-10-22 19:02:16 【问题描述】:我有以下代码让 GUI 响应集合中的更改。
myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI());
首先这是一个好方法吗?
第二:取消订阅此活动的代码是什么?是否相同但使用 -= (然后再次使用完整的匿名方法)?
【问题讨论】:
见this。 我没有将我的 lambda 表达式放在委托中(如您的链接中所示),因此我没有取消订阅的参考。 您/不能/保留参考文献有什么原因,就像在那个公认的答案中一样? ?重复:***.com/questions/183367/… 【参考方案1】:首先...是的,这是一种很好的做法,它简洁、小巧且易于阅读和理解...当然需要注意的是“除非您以后想退订”。
我相信Jon Skeet在那之前指出 “当涉及到使用匿名方法创建的委托的等效性时,规范明确不保证任何一种行为。”
因此,如果您稍后需要取消订阅该事件,您最好实际创建一个委托实例,以便您可以挂起该引用以供以后使用。
var myDelegate = delegate(sender, e)UpdateMyUI();
myObservableCollection.CollectionChanged += myDelegate;
myObservableCollection.CollectionChanged -= myDelegate;
【讨论】:
var myDelegate = delegate(sender, e)UpdateMyUI();不编译...您需要指定委托类型。 John Skeet 在他的示例中使用了 Action 委托,但这只需要一个参数。我们应该在您的示例中使用什么委托类型? @RaduSimionescu:与事件类型相同,在本例中为NotifyCollectionChangedEventHandler
【参考方案2】:
如果您需要取消订阅某个事件,则需要一个实例化引用。不幸的是,这意味着您不能使用该特定语法。
【讨论】:
如果“特定语法”是指创建 lambda 并在一行中添加处理程序,那么是的。简单的解决方案只是存储对 lambda 的引用。真的,我认为如果 OP 需要反复引用它,他应该考虑使用普通方法 - 至少在我看来,它提高了可读性。 @Noldorin 是的,这就是我所说的“特定语法”的意思。我完全同意你的看法。【参考方案3】:这是一个不错的方法,除非 myObservableCollection 的寿命比 'this' 长,在这种情况下,您最终可能会出现内存泄漏,因为在幕后创建的委托将保留对您的 ' 的引用这',这将使它保持活力。如果您反复创建和“销毁”正在侦听该事件的任何内容,您会发现垃圾收集器没有收集它们。
如果这是一个问题,您可以采用答案中建议的路线,保留对您必须首先创建的处理程序的引用。
另一个解决方案是使用弱引用来创建一个事件处理程序,如果没有其他引用,它将允许收集订阅者。我在this question and answer 中探索了这个解决方案。
【讨论】:
以上是关于如何取消订阅使用 lambda 表达式的事件?的主要内容,如果未能解决你的问题,请参考以下文章
C#入门详解笔记事件 泛型 委托 Lambda表达式 LINQ
Angular - Jasmine/karma - 订阅 lambda 表达式未执行
转UNITY3D 游戏开发之七C# 中的委托事件匿名函数Lambda 表达式