【发布时间】:2011-01-26 18:03:17
【问题描述】:
何时实施 IDisposable 的最佳做法是什么?
如果您在类中有一个托管对象,是实现它的最佳经验法则,还是取决于该对象是在类中创建还是只是传入?对于根本没有托管对象的类,我是否也应该这样做?
【问题讨论】:
-
@Earwicker:如果您在该主题上发现的比我更多,那么我会很感激您与我分享。
标签: c# .net vb.net idisposable
何时实施 IDisposable 的最佳做法是什么?
如果您在类中有一个托管对象,是实现它的最佳经验法则,还是取决于该对象是在类中创建还是只是传入?对于根本没有托管对象的类,我是否也应该这样做?
【问题讨论】:
标签: c# .net vb.net idisposable
如果您的意思是 非托管 对象,那么是的,只要您在班级中处理一个或多个非托管资源,您就应该实施它。当您可能持有本身是 IDisposable 的对象时,您也应该使用该模式,并确保在您的类被处置时处置它们。
(同意这个问题已经被问了足够多的时间了,如果打印出来,小型打印机的墨水就会用完......)
【讨论】:
虽然每个人都提到了(非托管)资源,但我还有一件事要补充:当我需要消除会阻止类超出范围并被垃圾收集的事件处理程序连接时,我会使用它。
例如,我有一个服务被注入到子视图中,该子视图将订阅服务上的各种异步完成类型事件。该子视图的所有者不知道具体类型是什么,它只是将其作为接口。该服务可能会在将来的某个任意时间超出范围,我不希望它在没有被 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 上的其他人对此有更多权威的 cmets,例如 Do event handlers stop garbage collection from occuring? 和 Garbage collection when using anonymous delegates for event handling。您可能还想查看这篇codeproject 文章。
【讨论】:
我认为the docs 非常清楚 IDisposable 的好处。
这个接口的主要用途是 释放非托管资源。这 垃圾收集器自动 释放分配给 a 的内存 当该对象为 no 时的托管对象 使用时间更长。然而,它不是 可以预测什么时候垃圾 将发生收集。此外, 垃圾收集器没有知识 非托管资源,例如窗口 句柄,或打开文件和流。
它甚至有一个例子。在该示例中,实现IDisposable 的类包含一个句柄。不再使用时需要释放句柄。这是在Dispose() 方法中完成的。因此,该类的用户看到它实现了IDisposable,并且知道当不再需要该类时需要显式处理它(因此可以释放句柄)。当不再需要实例时,您应该始终在 IDisosable 实例上调用 Dispose(),这是最佳实践(即规则)。
【讨论】:
当你的类持有你想在用完后释放的资源时,你应该实现 IDisposable。
【讨论】:
当你的类包含非托管对象、资源、打开的文件或数据库对象时,你需要实现IDisposable。
【讨论】:
如果它具有也需要处理的属性。
【讨论】: