如何取消订阅使用 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 表达式

如何将 C# lambda 表达式转换为委托?

使用 lambda 表达式时删除附加的事件处理程序 [重复]

如何对JavaFX lambda表达式进行反向工程并获取EventHandler和ActionListener的类定义