我什么时候应该实现IDisposable?

时间:2010-03-12 09:04:46

标签: c# .net vb.net idisposable

何时实施IDisposable的最佳做法是什么?

如果在类中有一个托管对象,那么实现它是最好的经验法则,还是依赖于对象是在类中创建还是只是传入?我是否也应该为没有托管对象的类做这件事?

6 个答案:

答案 0 :(得分:28)

如果您指的是非托管对象,那么只要您在班级中处理一个或多个非托管资源,就应该实施它。当您可能自己持有IDisposable的对象时,您也应该使用该模式,并确保在您的类处理时丢弃它们。

(同意这个问题已经被问过足够多的时间,如果要打印一台小型打印机的墨水......)

答案 1 :(得分:12)

虽然每个人都提到(非托管)资源,但我还有另外一件事要做:当我需要消除事件处理程序连接时,我会使用它,否则会阻止类超出范围并被垃圾收集。

作为一个例子,我有一个服务被注入到子视图中,该子视图将订阅服务上的各种异步完成类型事件。该子视图的所有者不知道具体类型是什么,它只是将其作为接口。该服务可能会在未来的某个任意点超出范围,我不希望它不被GC所左右。在删除该子视图后,所有者将调用Dispose来为其提供解除任何事件处理程序的机会。这是一个有点人为的(非常伪代码)示例,请注意子视图的接口如何实现IDisposable

public class OwnerView {

    public OwnerView() {
        _childView = new ChildView(myServiceReference);
    }

    public void CloseChildView() {
        if (childView != null) {
            _childView.Close();
            _childView.Dispose();
        }

        _childView = null;
    }

    private IChildView _childView;
}

public class ChildView : IChildView {

    public ChildView(MyService serviceRef) {
        _serviceRef = serviceRef;
        _serviceRef.GetSettingsAsyncFinished += new EventHandler(someEventHandler);
    }

    public void IDisposable.Dispose() {
        _serviceRef -= someEventHandler;
    }

    private MyService _serviceRef;
}

public interface IChildView : IDisposable {
    void DoSomething();
    ... etc ...
}

关于其他人在SO上有更多权威性评论,例如Do event handlers stop garbage collection from occuring?Garbage collection when using anonymous delegates for event handling。您可能还想查看此codeproject文章。

答案 2 :(得分:6)

当您的类在您使用完毕后拥有要释放的资源时,您应该实现IDisposable。

答案 3 :(得分:6)

当您的类包含非托管对象,资源,打开的文件或数据库对象时,您需要实现IDisposable

答案 4 :(得分:6)

我认为the docs非常清楚IDisposable有什么用处。

  

此界面的主要用途是   释放非托管资源。该   垃圾收集器自动   释放分配给a的内存   当该对象为no时,为托管对象   使用时间更长但事实并非如此   可以预测什么时候垃圾   收集将发生。此外,   垃圾收集器不知道   非托管资源,如窗口   处理,或打开文件和流。

它甚至有一个例子。在该示例中,实现IDisposable的类包含句柄。不再使用时,需要释放句柄。这是在Dispose()方法中完成的。因此,该类的用户看到它实现了IDisposable并且知道在不再需要该类时需要明确地处理该类(因此可以释放句柄)。最佳实践(即规则),当不再需要实例时,您应始终在Dispose()个实例上调用IDisosable

答案 5 :(得分:0)

如果它具有需要处理的属性。