代码之家  ›  专栏  ›  技术社区  ›  Gerrie Schenck

如何取消订阅使用lambda表达式的事件?

  •  26
  • Gerrie Schenck  · 技术社区  · 15 年前

    我有以下代码让GUI响应集合中的更改。

    myObservableCollection.CollectionChanged += ((sender, e) => UpdateMyUI());
    

    首先,这是一个很好的方法吗?

    第二:取消订阅此活动的代码是什么?是否相同,但使用-=(然后再次使用完整的匿名方法)?

    3 回复  |  直到 15 年前
        1
  •  20
  •   J. Steen    15 年前

    如果需要取消订阅事件,则需要实例引用。不幸的是,这意味着您不能使用那个特定的语法。

        2
  •  35
  •   Community rcollyer    7 年前

    首先…是的,这是一个很好的方法,它干净,小的形式,易于阅读和理解…当然,警告是“除非你以后想退订”。

    我相信 Jon Skeet 在那之前指出 “当涉及到使用匿名方法创建的委托的等效性时,规范明确地不保证任何一种方式的行为。”

    因此,如果您以后需要取消订阅事件,最好实际创建一个委托实例,这样您就可以挂起引用以备以后使用。

    var myDelegate = delegate(sender, e){UpdateMyUI()};
    
    myObservableCollection.CollectionChanged += myDelegate;
    
    myObservableCollection.CollectionChanged -= myDelegate;
    
        3
  •  1
  •   Community rcollyer    7 年前

    这是一个不错的方法,除非MyObserveableCollection的寿命将长于“this”,在这种情况下,您可能会导致内存泄漏,因为在后台创建的委托将保留对“this”的引用,这将使其保持活动状态。如果您重复创建和“销毁”正在侦听事件的内容,您将发现垃圾收集器没有收集这些内容。

    如果这是一个问题,您可以按照答案中建议的路线走,保存对处理程序的引用,必须首先创建该引用。

    另一种解决方案是使用弱引用创建事件处理程序,该处理程序允许在没有其他引用的情况下收集订阅服务器。我已经在 this question and answer .