关于c#:我什么时候应该实现IDisposable?

When should I implement IDisposable?

本问题已经有最佳答案,请猛点这里访问。

何时实现IDisposable的最佳实践是什么?

如果类中有一个托管对象,那么实现它的最佳经验法则是什么?还是取决于对象是在类中创建的还是刚刚传入的?我还应该为根本没有托管对象的类执行此操作吗?


如果您的意思是非托管对象,那么是的,您应该在类中处理一个或多个非托管资源时实现它。当您可能持有可IDisposable本身的对象时,也应该使用模式,并确保在释放类时释放它们。

(同意这个问题已经被问了足够的时间,以便在打印时用完小打印机的墨水…)


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

例如,我有一个注入到子视图中的服务,该子视图将订阅该服务上的各种异步完成类型事件。该子视图的所有者不知道具体类型是什么,它只是将其作为接口。将来,服务可能会在某个任意点超出范围,我不希望它挂在未被GC处理的地方。在摆脱该子视图后,所有者将调用Dispose来给它取消挂起任何事件处理程序的机会。下面是一个稍微做作(非常伪代码)的示例,请注意子视图的接口如何也实现IDisposable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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 ...
}

其他人对此有更权威的评论,比如事件处理程序是否阻止垃圾收集的发生?以及使用匿名委托进行事件处理时的垃圾收集。您也可以查看此代码项目文章。


我认为医生们很清楚什么是iDisposable的好处。

The primary use of this interface is
to release unmanaged resources. The
garbage collector automatically
releases the memory allocated to a
managed object when that object is no
longer used. However, it is not
possible to predict when garbage
collection will occur. Furthermore,
the garbage collector has no knowledge
of unmanaged resources such as window
handles, or open files and streams.

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


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


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


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