2016-01-21 13 views
5

根据Essential C# 6.0类调​​用.Dispose(),你应该:上有一个终结

避免在有一个终结所拥有的对象调用Dispose()。 取而代之,依靠最终化队列来清理实例。

  1. 可能有人请详细说明这是我不是什么处分的一点是,如果我们不能从拥有的对象调用它清楚了吗?
  2. 除了Reflection,你会如何判断对象是否有Finalizer
  3. 除了搜索API文档(如果您有权访问它并存在)或反射,您如何找出何时调用Close()/Close() + Dispose()?我在网络上看到很多关于特定类型的问题(MemoryStream/Form/SqlConnection/etc),但我更多地关注“如何自己弄清楚”。

按照Dispose Pattern你应该:

考虑提供方法Close()除Dispose()方法,如果是靠近该地区的标准术语。这样做时,使关闭实现与Dispose相同并考虑显式实现IDisposable.Dispose方法非常重要。

,但有些时候,你应该像Form同时调用等类似问题“Close and Dispose - which to call?”接近但也有来自

是没有定义的方法除了像往常一样,答案是:这要看情况。不同的类以不同的方式实现IDisposable,并且由您来做必要的研究。

编辑:以下是完整的指南,问我有没有允许复制,但因为它是一个指导方针(从而假定它应该被自由共享的公共知识)和实际培训材料不是某一部分,我希望我没有违反任何规则。

准则
DO只能用于使用稀缺或昂贵的资源对象实现一个终结方法,即使最终确定延迟垃圾回收。
DO实现IDisposable来支持带终结器的类的确定性终结。
如果Dispose()未被明确调用,那么在实现IDisposable的类上实现一个终结器方法。
重构一个终结方法来调用与IDisposable相同的代码,也许只需调用Dispose()方法即可。
不要抛出终结器方法的异常。
从Dispose()调用System.GC.SuppressFinalize()以避免重复资源清理并延迟对象的垃圾回收。
确保Dispose()是幂等的(应该可以多次调用Dispose())。
保持Dispose()简单,侧重于最终确定所需的资源清理。
AVOID在拥有终结器的拥有对象上调用Dispose()。相反,依靠最终化队列来清理实例。
AVOID引用其他在定稿过程中未定稿的对象。
重写Dispose()时,DO调用基类的Dispose()方法。
考虑确保在调用Dispose()后对象变得不可用。处理完一个对象之后,除Dispose()(可能会多次调用它)之外的其他方法应抛出ObjectDisposedException。
DO对拥有一次性字段(或属性)的类型执行IDisposable并处理所述实例。

回答

6
  1. 可能有人请详细说明这是我不是什么处分的一点是,如果我们不能从拥有的对象调用它清楚了吗?

没有图书的全部内容和背景(我没有书的副本,也可能很多人读你的问题),这是不可能肯定他们的意思说。但它应该是一本很好的书,因此我必须假设你所引用的文本只适用于只有才能在自己的终结器中编码。即当然,你应该正常处置拥有的物品。在你的Dispose()方法。

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

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

  1. 除了Reflection之外,如何判断对象是否有Finalizer?

除了反射,你会依靠源代码(如果可用),文件(如书面),或仅仅是对象实现IDisposable的事实(即做一个假设…现在不有保证,但两者之间有很强的相关性)。

更重要的是,注意,因为它是能够正确执行,如果没有使用终结(实现IDisposable对象例如,如果您使用SafeHandle,或者如果实现IDisposable只有这样您就可以明确地清理国有IDisposable对象),不能保证终结者的存在。

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

  • 你如何找出何时调用close()/关闭()+ Dispose()方法除了搜索API文档(如果你有机会获得它,它的存在)还是反思?我在网络上看到很多关于特定类型(MemoryStream/Form/SqlConnection /等)的问题,但我更多地关注“如何自己弄清楚”。
  • 你不能。不是没有仔细检查代码。这说…

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

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

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

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


    附录:

    我做了一个小的浏览周围。当然,在Stack Overflow上有很多关于GC,定稿,IDisposable,终结器等的文章,但是我没有看到任何似乎与你的问题直接等价的东西。这其中似乎虽然最接近:

    Which objects can I use in a finalizer method?

    其他人,可能是有用的附加阅读:

    When would dispose method not get called?
    Why call Dispose()? Memory leak won't occur?
    IDisposable and managed resources

    和当然,经典:
    Proper use of the IDisposable interface

    +2

    关于如何做适当的资源处置,我见过最好的非SO文章是“[IDisposable:你的母亲从来没有告诉过你关于资源释放](http://www.codeproject.com/Articles/29534/IDisposable-What - 你的母亲从来没有告诉你关于)“[斯蒂芬Cleary](http://stackoverflow.com/users/263693/stephen-cleary) –

    +0

    这是一个很好的答案彼得,我已经添加完整指南。在发布准则之后,重新阅读准则和您的评论,从我的角度来看,您认为它看起来像是与终结者有关,而我在与IDisposable有关的印象之下是正确的。Dispose()这就是为什么我很困惑。我也喜欢你对第2点的回答,我可以在SafeHandles上进行一些进一步的研究。关于第3点,似乎纯粹的经验和试验和错误几乎是一天的顺序。我的强迫症很激动。 – Storm

    +0

    @Storm我在上一篇评论中链接到的文章讨论了SafeHandles如何工作以及如何正确*实现您自己的。 –

    相关问题