在具有Finalizer的类上调用.Dispose()

根据Essential C#6.0,您应该:

AVOID在拥有终结器的拥有对象上调用Dispose()。 相反,依靠最终化队列来清理实例。

  • 有人可以请详细说明这一点,因为我不清楚Dispose的意义是什么,如果我们不从拥有的对象中调用它的话?
  • 除了Reflection之外,你如何确定对象是否有Finalizer
  • 除了搜索API文档(如果您有权访问它并存在)或反射之外,您如何确定何时调用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的意义是什么,如果我们不从拥有的对象中调用它的话?
  • 如果没有这本书的全文及其背景(我没有这本书的副本,也没有其他许多人阅读你的问题),不可能确定它们的含义。 但它应该是一本很好的书,因此我必须假定你所引用的文本只是用于你自己的终结器中的代码。 也就是说,你应该正常地处置拥有的物品。 在你的Dispose()方法中。

    这是关于如果你的对象没有妥善处理该怎么办。 答案就是清理你自己的非托管资源。

    与此相关的是,现在,随着SafeHandle类的出现(不久前),您可能根本不需要终结器。 相反,将自己的非托管资源包装在SafeHandle子类中,并让该类处理完成。

  • 除了Reflection之外,你如何确定对象是否有Finalizer?
  • 除了反思,你会依赖于源代码(如果有的话),文档(如果书面),或者简单的事实,该对象实现IDisposable (即做一个假设......它不能保证,但之间有强烈的相关性他们俩)。

    更重要的一点是,请注意,由于可以在不使用终结器的情况下正确实现实现IDisposable的对象(例如,如果您使用SafeHandle ,或者仅实现IDisposable以便确定性地清理拥有的IDisposable对象)的终结者不能保证。

    我认为一个更好的方式来指导指导将是“不要在终结器中处理对象”。 依靠IDisposable对象本身以某种方式处理完成自己拥有的资源的事实,并只关注您自己的对象直接拥有的任何非托管资源。

  • 除了搜索API文档(如果您有权访问它并存在)或反射之外,您如何确定何时调用Close()/ Close()+ Dispose()? 我在网络上看到很多关于特定类型(MemoryStream / Form / SqlConnection /等)的问题,但我更多地关注“如何自己弄清楚”。
  • 你不能。 不是没有仔细检查代码。 那说...

    你不应该同时调用Close()Dispose() 。 如果课程正确实施,两者应始终等同。

    当然,.NET中没有任何东西可以实现这一点。 所以不可能肯定地说你不需要。 但是,如果你正在处理一种需要两者的类型,那么它写得很差,并且可能会以其他方式破坏。 最好避免完全使用这种类型。 :)

    当然,正如你指出的那样, 在某些情况下Form类需要你调用Close()Dispose() (在大多数情况下,调用Close()实际上是足够的......这只是因为他们实现模态的奇怪方式对话框,你会得到规则的例外)。 但是这是一个非常老的API,在完全理解IDisposable模式的复杂性之前设计。 人们希望微软今天不要再以同样的方式设计这个API,如果他们必须再次这样做的话(事实上,WPF没有那样的二分法)。

    现代实现应该更好地遵循更加一致的良好惯例。


    附录:

    我做了一些浏览。 当然,在Stack Overflow上有很多关于GC,finalization, IDisposable ,finalizer等的文章,但是我没有看到任何似乎与你的问题直接等价的东西。 尽管这个看起来最接近:

    我可以在终结器方法中使用哪些对象?

    其他可能有用的补充阅读:

    何时处置方法不被调用?
    为什么要调用Dispose()? 内存泄漏不会发生?
    一次性使用和管理资源

    当然,经典的:
    正确使用IDisposable接口

    链接地址: http://www.djcxy.com/p/54537.html

    上一篇: Calling .Dispose() on a class that has a Finalizer

    下一篇: Few Questions to Memory management in .net