C#我应该手动删除我声明的事件处理程序吗?

C#我应该手动删除我声明的事件处理程序吗?,c#,event-handling,C#,Event Handling,好的,在这里举个例子: 我有UserControl A、UserControl B、UserControl C和一个Windows窗体 此Windows窗体仅由UserControl A启动 UserControl C有[Next]和[Back]按钮 比如说,UserControl A是用事件处理程序声明的。UserControl A中的一个函数将实际引发事件调用,以在UserControl C执行一个函数。 因此,在UserControl C中,我必须添加 “UserControlA.OneF

好的,在这里举个例子:

  • 我有UserControl A、UserControl B、UserControl C和一个Windows窗体
  • 此Windows窗体仅由UserControl A启动
  • UserControl C有[Next]和[Back]按钮
  • 比如说,UserControl A是用事件处理程序声明的。UserControl A中的一个函数将实际引发事件调用,以在UserControl C执行一个函数。
  • 因此,在UserControl C中,我必须添加
  • “UserControlA.OneFunction+=此.UserControlC_函数;”

  • 如果我单击UserControl C上的Next按钮,它将处理UserControl A并将新的UserControl B添加到Windows窗体中。但我从不手动删除此事件处理程序
  • UserControl A中的一个函数是调用方(声明事件的地方)。
    UserControl C中的一个函数是侦听器

    因此,以下是我的问题:

    • 在释放UserControl A之前,是否应手动删除处理程序?
    • 此用户控制dispose是否会自动删除先前声明的处理程序
    • 我应该把这个加在什么地方吗
    “UserControlA.OneFunction-=此.UserControlC_函数;”

  • 按照惯例,我们没有。而且,由于在处理之后不应调用任何事件,因此没有必要这样做,除非所讨论的控件行为异常
  • 不,至少从反射器上看不到这样的代码

  • 在这种情况下,您不需要删除处理程序,因为表单及其按钮都没有被表单外部的代码引用,因此,整个对象图将被垃圾收集。

    这篇文章的答案非常好地解释了何时需要手动删除事件处理程序以及何时不需要

    如果表单已发布(假设没有其他对象引用所讨论的对象),则不删除事件处理程序的风险很小,但是最好在无法再访问侦听对象之前删除事件处理程序(即所有引用范围内对象的变量)不这样做会造成内存泄漏

    在您的情况下,情况并非如此(如果我了解您所描述的内容,代码将使其更加清晰)
    问题是,如果将引用对象C的委托附加到对象a上的事件,然后取消对C的访问(例如,为变量指定新值)。如果事件发布者的内存生存期不受事件订阅者可用生存期的限制,则取消订阅事件的失败可能会导致内存泄漏。如果不是因为这样做带来的麻烦,那么被处置的事件订阅者没有理由不取消所有事件的订阅,被处置的事件发布者也没有理由不取消所有事件订阅。然而,由于C#和VB都没有提供任何方便的方法来做这些事情,因此,我们必须在妥善处理订阅的麻烦和在许多情况下可以省去浏览的事实之间取得平衡。

    请扩展第二行,比如,我在Windows窗体中手动添加了一个事件处理程序,以便在UserControl上触发一个函数调用?感谢请澄清:哪一个是事件源,哪一个是侦听器?如果我总是按“下一步”和“上一步”按钮会怎么样?比如说:UserControl C有[Next]和[Back]按钮来控制UserControl A和UserControl B,就像安装向导一样。每次按下[下一步]按钮时,将执行此“ctlContent.ctlRBContent1_GetBuildName+=this.GetBuildName;”。但这一事件永远不会消失。这将是什么?然而,在失去对C的引用之前删除处理程序是一个好主意。在这种特殊情况下,这不应该是一个真正的问题,但始终这样做是一个好习惯it@Rune,你的意思是我可以对析构函数执行吗?@lannyboy:一旦一个控件被释放,它就再也不能正常使用了。其消息循环被终止,其WndProc将被注销。因此,只要您正确地处理了控件,它就会正常工作。是的,我的意思是“当您需要手动删除…”。我做了编辑。谢谢。是的,我现在明白你的意思了。因此,在释放控件之前,我们必须手动删除事件处理程序。@lannyboy:如果表单和控件将同时被放弃,那么放弃订阅不会造成内存泄漏;例如,如果控件持有来自长寿命对象的更改通知事件的订阅,则将表单订阅给控件的事件可能会导致原本可能是“小”内存泄漏的更大内存泄漏(因为控件会使表单保持活动状态,而表单可能使其他控件保持活动状态,等等)。至于使用100字节的内存泄漏是否比使用meg的内存泄漏更好或更糟,有不同的思想流派。如果有固定数量的创建-放弃循环(例如,100个),那么如果它们总共使用10000字节比使用100000000字节要好。另一方面,如果一个程序每分钟执行一次创建/放弃循环,那么在一天之内,如果每个这样的循环都绑定一个meg,那么很明显会出现问题。如果每一个这样的周期只需要100个字节,就可以在只使用一兆额外存储的情况下运行该程序一周,但是处理订阅的速度会越来越慢,直到它阻塞系统。