题 EventHandlers和C#Classes析构函数/ Dispose


我对C#Classes和它们的解构函数有点困惑。

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

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

当Foo类被销毁时,我需要取消订阅该事件。我实施吗 IDisposable 在那里或在解构器中取消订阅?我需要消耗那些事件,我不能以另一种方式去做。

对于其中一个类,我创建一个实例,检查进度,然后类实例超出范围。对于另一个它留在 MainForm 直到表格关闭。第一个是我担心的,因为它可能仍然有对该事件处理程序的引用而且没有正确地去。

我不想泄漏内存。何时以及如何取消订阅?


23
2017-08-17 12:51


起源




答案:


不要在析构函数中执行它,因为在附加事件处理程序时不会调用它:当你附加Foo的实例方法作为Bar事件的处理程序时,Bar将保存对Foo的引用,所以Foo不会被垃圾收集,也不会调用它的析构函数。

您应该实现IDisposable,并显式处理您的对象

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

25
2017-08-17 13:05



啊!除非我们清理非托管代码,否则我认为我们不应该实现IDisposable? - Sarah Fordington
IDisposable可以出于其他原因实现,它不仅限于清理非托管资源...... - Thomas Levesque
如果您查看常见的Disposable Pattern,则可以使用一条路径来处理托管和非托管资源。大多数情况下,您只拥有非托管资源和/或托管资源。但是对于你的情况,只有拥有应该清理的托管资源也没关系。 - Oliver
要完成Oliver的评论,这里有一个有用的链接: msdn.microsoft.com/en-us/library/b1yfkh5e.aspx - Thomas Levesque


如果你曾经遇到过让A类成为一个长期存在的类的问题,那么B类是订阅A类事件的短命类型,那么你可能会感兴趣的是 弱事件模式。这可能是一个你没有发现的问题,直到它迟到,即 普林斯顿自驾车。


3
2017-08-22 06:26