在具有Finalizer的类上调用.Dispose()
根据Essential C#6.0,您应该:
AVOID在拥有终结器的拥有对象上调用Dispose()。 相反,依靠最终化队列来清理实例。
Finalizer
? Close()
/ Close()
+ Dispose()
? 我在网络上看到很多关于特定类型( MemoryStream
/ Form
/ SqlConnection
/等)的问题,但我更多地关注“如何自己弄清楚”。 根据配置模式,您应该:
考虑提供方法Close(),除了Dispose()之外,如果close是区域中的标准术语。 这样做时,使关闭实现与Dispose相同并考虑显式实现IDisposable.Dispose方法非常重要。
但有些时候你应该像Form
一样打电话等。像“关闭和处置 - 要打电话的问题?”等问题。 接近,但除此之外没有明确的方法
像往常一样,答案是:这取决于。 不同的类以不同的方式实现IDisposable,并且由您来做必要的研究。
编辑:这是完整的指南,我没有要求复制许可,但由于它是一个指导原则(因此假设它应该是免费共享的公共知识),而不是实际培训材料的某些部分,没有违反任何规则。
方针
DO仅在资源稀缺或昂贵的对象上实现终结器方法,尽管最终化会延迟垃圾回收。
DO实现IDisposable以支持使用终结器的类的确定性定稿。
如果Dispose()未被明确调用,请在实现IDisposable的类上实现终结器方法。
DO重构一个终结方法来调用与IDisposable相同的代码,也许只需调用Dispose()方法即可。
不要抛出终结器方法的异常。
请从Dispose()调用System.GC.SuppressFinalize()以避免重复资源清理并延迟对对象的垃圾回收。
确保Dispose()是幂等的(应该可以多次调用Dispose())。
请保持Dispose()简单,关注最终确定所需的资源清理。
AVOID在拥有终结器的拥有对象上调用Dispose()。 相反,依靠最终化队列来清理实例。
避免引用在定稿过程中未完成的其他对象。
重写Dispose()时,DO调用基类的Dispose()方法。
考虑确保在调用Dispose()后对象变得不可用。 处理完一个对象之后,除Dispose()(可能会多次调用它)之外的其他方法应抛出ObjectDisposedException。
对具有一次性字段(或属性)的类型执行IDisposable并处理所述实例。
如果没有这本书的全文及其背景(我没有这本书的副本,也没有其他许多人阅读你的问题),不可能确定它们的含义。 但它应该是一本很好的书,因此我必须假定你所引用的文本只是用于你自己的终结器中的代码。 也就是说,你应该正常地处置拥有的物品。 在你的Dispose()
方法中。
这是关于如果你的对象没有妥善处理该怎么办。 答案就是清理你自己的非托管资源。
与此相关的是,现在,随着SafeHandle
类的出现(不久前),您可能根本不需要终结器。 相反,将自己的非托管资源包装在SafeHandle
子类中,并让该类处理完成。
除了反思,你会依赖于源代码(如果有的话),文档(如果书面),或者简单的事实,该对象实现IDisposable
(即做一个假设......它不能保证,但之间有强烈的相关性他们俩)。
更重要的一点是,请注意,由于可以在不使用终结器的情况下正确实现实现IDisposable
的对象(例如,如果您使用SafeHandle
,或者仅实现IDisposable
以便确定性地清理拥有的IDisposable
对象)的终结者不能保证。
我认为一个更好的方式来指导指导将是“不要在终结器中处理对象”。 依靠IDisposable
对象本身以某种方式处理完成自己拥有的资源的事实,并只关注您自己的对象直接拥有的任何非托管资源。
你不能。 不是没有仔细检查代码。 那说...
你不应该同时调用Close()
和Dispose()
。 如果课程正确实施,两者应始终等同。
当然,.NET中没有任何东西可以实现这一点。 所以不可能肯定地说你不需要。 但是,如果你正在处理一种需要两者的类型,那么它写得很差,并且可能会以其他方式破坏。 最好避免完全使用这种类型。 :)
当然,正如你指出的那样, 在某些情况下 , Form
类需要你调用Close()
和Dispose()
(在大多数情况下,调用Close()
实际上是足够的......这只是因为他们实现模态的奇怪方式对话框,你会得到规则的例外)。 但是这是一个非常老的API,在完全理解IDisposable
模式的复杂性之前设计。 人们希望微软今天不要再以同样的方式设计这个API,如果他们必须再次这样做的话(事实上,WPF没有那样的二分法)。
现代实现应该更好地遵循更加一致的良好惯例。
附录:
我做了一些浏览。 当然,在Stack Overflow上有很多关于GC,finalization, IDisposable
,finalizer等的文章,但是我没有看到任何似乎与你的问题直接等价的东西。 尽管这个看起来最接近:
我可以在终结器方法中使用哪些对象?
其他可能有用的补充阅读:
何时处置方法不被调用?
为什么要调用Dispose()? 内存泄漏不会发生?
一次性使用和管理资源
当然,经典的:
正确使用IDisposable接口