处理IDisposable的最佳实践

我有一个类层次结构,每个成员可以创建IDisposable对象。

我将List属性添加到此层次结构中的基类,我在创建时向其添加任何一次性对象。 根Dispose方法遍历此列表并为其列表中的每个项调用Dispose并清除列表。 在应用程序中,我显式调用顶层对象的Dispose方法,导致处理级联层次结构。

这有效,但还有更好的方法吗? 我是否在无意中重复了框架中已有的某些function?

(注意 – 有问题的对象的生命周期不能将它们包装在一个using块中,或者在创建它们的同一个using处理它们。)

编辑

只是为了澄清 – 我只是保留那些需要保留的对象。 有些是在创建它们的同一方法中处理掉的,但是很多都是以不可能的方式使用的。

只要你正确实现一次性模式(如此处所述),这种方法就可以了。

据我所知,只有using语句才能对IDisposable提供特殊支持 – 框架中没有任何东西可以复制你正在做的事情。

不,那是对的。 IDisposable旨在释放非托管资源,应在完成实例后尽快调用。 这是一种常见的误解,认为这是不必要的,或者当对象被垃圾收集时,finailizer会自动执行此操作。 它不是。

IDisposable的正确模式在这里 ,包含在下面以供快速参考。

 public class Resource : IDisposable { // Dispose() calls Dispose(true) public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // NOTE: Leave out the finalizer altogether if this class doesn't // own unmanaged resources itself, but leave the other methods // exactly as they are. ~Resource() { // Finalizer calls Dispose(false) Dispose(false); } // The bulk of the clean-up code is implemented in Dispose(bool) protected virtual void Dispose(bool disposing) { if (disposing) { // free managed resources } // free native resources here if there are any } } 

如果你在谈论任意IDisposable对象,我不相信它存在。

System.ComponentModel.Container类实现级联Dispose,但要求元素实现IComponent 。 如果您控制IDisposable对象,您可以使它们实现IComponent – 它只需要实现一个可以返回null属性Site

听起来像访客模式可能合适的情况。 虽然我从不理解它扩展你的类并保持不变的说法,因为我只知道类应该有AcceptVisitor方法的例子。 顺便说一下,这不是我喜欢的模式,因为它很复杂并且往往会使代码混乱。

如果一个对象将创建许多其他IDisposable对象并在其存在期间保持对它们的所有权,那么您描述的模式可能是一个好对象。 可以通过让你的类实现方法“T RegDispos (T thing)T:IDisposable”来增强它。 这将在列表中添加一次性并返回它。 因此,可以通过替换诸如“someField = someDisposType.CreateThing();”之类的语句来处理同一语句中资源的创建和清理。 with“someField = RegDispos(someDisposType.CreateThing());”。

如果你的类没有暴露公共构造函数(需要外人使用工厂方法),如果你要么使用vb.net或者愿意使用线程静态字段,你甚至可以将初始化和清理与声明结合起来(例如“ var someField = RegDispos(someDisposType.CreateThing());“)。 为了安全起见,必须在try / catch或try / finally块中调用构造函数,如果构造失败,可以在创建的子对象上调用Dispose。 因为C#中的字段初始化程序无法访问构造函数参数(语言中的弱点,恕我直言),实现这种模式的唯一方法是让工厂方法创建列表并将其放入线程静态变量中然后通过静态RegDispos方法读取。