【问题标题】:EventHandlers and C# Classes destructor/DisposeEventHandlers 和 C# 类的析构函数/Dispose
【发布时间】:2010-11-20 05:49:17
【问题描述】:

我对 C# 类及其解构器有点困惑。

我必须在构造函数中获取的类实例中使用一些事件处理程序:

 public Foo(IFooHandler handler)
 {
     handler.Load += Load;
     handler.Close += Close;
 }

当 Foo 类被销毁时,我需要取消订阅该事件。我是在其中实现IDisposable 并在其中取消订阅,还是在解构函数中?我需要消耗这些事件,我不能以其他方式做到这一点。

对于其中一个类,我创建了一个实例,检查进度,然后该类实例超出范围。另一方面,它保留在MainForm 中,直到表单关闭。第一个是我担心的,因为它可能仍然有对该事件处理程序的引用并且不能正常运行。

我不想泄露内存。我应该何时以及如何退订?

【问题讨论】:

    标签: c# winforms events delegates


    【解决方案1】:

    不要在析构函数中这样做,因为在附加事件处理程序时不会调用它:当您附加 Foo 的实例方法作为 Bar 事件的处理程序时,Bar 将持有对 Foo 的引用,所以 Foo 不会被垃圾回收,也不会调用它的析构函数。

    您应该实现 IDisposable,并明确地处置您的对象

    public void Dispose()
    {
        if (handler != null)
        {
            handler.Load -= Load;
            handler.Close -= Close;
        }
    }
    

    【讨论】:

    • 啊!我认为除非我们清理非托管代码,否则我们不应该实现 IDisposable?
    • IDisposable 可以出于其他原因实现,它不仅限于清理非托管资源...
    • 如果您看一下常见的 Disposable 模式,就会发现处理托管和非托管资源的路径。大多数情况下,您只有非托管资源和/或托管资源。但是对于您的情况,也可以只拥有应该清理的托管资源。
    • 要完成 Oliver 的评论,这里有一个有用的链接:msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
    【解决方案2】:

    如果您曾经遇到过让 A 类是一个长期存在的类而 B 类是订阅 A 类事件的短期类的问题,那么您可能会对 Weak Event Pattern 感兴趣。这可能是一个你直到很晚才发现的问题,即Princeton self driving car.

    【讨论】:

    • 哈哈哈。自动驾驶内存泄漏的重要链接。我正在处理一个项目的静态事件处理程序,并想知道所有的大惊小怪是否值得。这个链接让我很开心。
    猜你喜欢
    • 2013-07-26
    • 2011-12-29
    • 2012-12-08
    • 2019-11-09
    • 2011-09-01
    • 2014-05-27
    • 1970-01-01
    • 2014-08-08
    相关资源
    最近更新 更多