我什么时候应该实现IDisposable?

Bob*_*bby 37 .net c# vb.net idisposable

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

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

pep*_*ppy 29

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

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


slu*_*ter 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 ...
}
Run Code Online (Sandbox Code Playgroud)

关于SO的其他人有更多权威的评论,比如Do事件处理程序会阻止垃圾收集吗?匿名委托进行事件处理时的垃圾收集.您可能还想查看此代码项目文章.


Arv*_*rve 6

当您的类包含您在完成使用它们时要释放的资源时,应该实现IDisposable.


Sun*_*nil 6

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


bit*_*onk 6

我认为文档很清楚IDisposable有什么用处.

此接口的主要用途是释放非托管资源.当不再使用该对象时,垃圾收集器会自动释放分配给托管对象的内存.但是,无法预测垃圾收集何时发生.此外,垃圾收集器不了解非托管资源,例如窗口句柄,或打开文件和流.

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