IDisposable 和托管资源 [重复]

Posted

技术标签:

【中文标题】IDisposable 和托管资源 [重复]【英文标题】:IDisposable and managed resources [duplicate] 【发布时间】:2011-12-20 05:08:26 【问题描述】:

可能重复:Proper use of the IDisposable interface

我有一个同时具有托管和非托管资源的类。我正在使用 IDisposable 来释放非托管资源。我应该在 dispose 方法中释放托管资源吗?或者我可以把它留给 GC 来释放托管资源?

【问题讨论】:

你certainly should,详情见链接文章。 你应该。 Here 是一篇帮助你正确实现 IDisposable 模式的文章。 使用 SafeHandle 将非托管资源转换为托管资源并使用 Dispose() 将它们全部清理干净。在链接的骗局中查看 Scott Dorman 的回答。 【参考方案1】:

如果你看看下面的documentation,你会发现这一行:

释放类型在其 Dispose 方法中拥有的任何一次性资源。

因此,在您的处置方法中,您应该处置也实现 IDisposable 的托管资源。如果一个对象没有实现这一点,你不必处置它。

【讨论】:

【参考方案2】:

我建议带有终结器的类(C# 编译器为任何带有析构函数的类生成终结器)应避免持有对不会在终结中使用的任何对象的引用。除了相对较少的例外,持有封装在对象中的资源的类应避免持有未如此封装的资源。相反,这些资源应该封装到它们自己的对象中,这样它们就可以与其他包含资源的对象一起保存。

一旦处理完毕,任何拥有封装在其他对象中的资源的类的正确行为通常是在其自己的 Dispose 方法中对所有此类资源调用 Dispose,而不是实现终结器(并且 - - 对于 C#-- 没有析构函数,这会导致编译器生成终结器)。如果终结器在包含其他可终结对象的对象上运行,则这些对象中的每一个通常都处于以下三种状态之一:

    其他对象上的终结器已经运行,在这种情况下,无需执行任何操作来清理它。 其他对象上的终结器将被安排运行,在这种情况下,可能不需要做任何事情来清理它。 其他对象可能存在其他强引用,在这种情况下,它不应该被清除。

只有在第二种情况下,才有理由考虑对另一个对象进行任何清理。

注意,顺便说一句,除了释放对象实例直接消耗的内存之外,几乎不应该依赖垃圾收集器来做任何事情。确定性处置几乎总是要好得多。唯一应该故意使用垃圾收集器来清理资源的情况是,当人们要创建成本相对较低的资源时,这些资源已知会在垃圾收集时有效地清理自己,并且实例将足够广泛分享说,找出最后一个离开范围的时间是不切实际的。虽然有时放弃一次性物品有很好的理由,但没有正当理由放弃一次性物品总是一个错误(如果放弃一次性物品是适当的,那么证明自己这样做的理由是适当的)。

【讨论】:

以上是关于IDisposable 和托管资源 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

非托管资源、IDisposable 和自定义类型

接口IDisposable的用法

IDisposable

哪个类“拥有”非托管资源(并且实现了 IDisposable)?

IDisposable 模式。我的终结者如何处理免费的托管资源?

IDisposable接口