Dispose vs Dispose(bool)

时间:2011-03-07 20:58:13

标签: c# dispose

我对处理感到困惑。我正在尝试让我的代码正确处理资源。所以我一直将我的类设置为IDisposable(使用Dispose方法),确保调用Dispose方法。

但是现在FXCop告诉我很多关于Disposing = false和调用Dispose(false)的东西。

我没有看到采用bool的Dispose方法。我需要制作一个吗?如果是这样,为什么?为什么不在处理时调用一个方法呢?

我在这里看到了一些代码:http://msdn.microsoft.com/en-us/library/ms244737.aspx,它展示了如何制作一个带有bool的Disposing方法。它表示它适用于本地和管理资源。 但我认为处理的全部内容仅适用于非托管资源。

此外,FXCop抱怨的是:

    ~OwnerDrawnPanel()
    {
        _font.Dispose();
    }

它说:

  

CA1063:Microsoft.Design:修改'OwnerDrawnPanel .~ OwnerDrawnPanel()',使其调用 Dispose(false),然后返回。

但Font上没有Dispose(bool)(我能找到)。

总结一下:

为什么我需要Dispose(bool)?如果我这样做,为什么Font没有呢?因为它没有它,为什么FXCop要求我使用它?


感谢所有出色的答案。我想我现在明白了。这是

我看到答案:

处置“非托管”资源分为两类:

  1. 包含在托管类(即Bitmap,Font等)中的资源,但仍需要调用Dispose来正确清理它们。
  2. 您已分配的资源,即本机资源的表示(即需要发布的设备上下文)
  3. Dispose(bool)用于区分两者:

    1. 当您的对象直接调用Dispose时,您希望释放两种“非托管”资源。
    2. 当您的对象用于垃圾收集时,您无需担心第一种资源。垃圾收集器在清理它们时会处理它们。您只需要担心已分配的真实本机资源(如果有)。

10 个答案:

答案 0 :(得分:8)

Dispose(bool)是实施FinalizeDispose清理非托管资源的模式,see this for detail

答案 1 :(得分:7)

Dispose(bool)并非公开,这就是您在Font上看不到的原因。

如果您班级的某些用户忘记在您的方法上调用Dispose,您将通过拨打Dispose(false)中的Finalizer来释放非托管资源

如果正确调用了IDispose,则调用托管资源上的Dispose,处理非托管资源。

标志是区分这两种情况。

这是MSDN推荐的模式。

答案 2 :(得分:7)

IDisposable提供了一个带签名的方法

public void Dispose()

Microsoft最佳做法(http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx)建议使用签名

制作第二个私有方法
private void Dispose(bool)

您的公共Dispose方法和Finalizer应调用此私有Dispose方法以防止多次处理受管资源。

您可以通过在dispose方法中实现IDisposable和处理字体对象,或在类中创建Dispose(bool)方法,并使终结器调用该方法来修复您获得的警告。

答案 3 :(得分:3)

FxCop说你应该实现像here所述的Disposable模式。请注意,您应not使用终结器来处理托管资源,例如_font。终结器用于清理非托管资源。如果不在(子)类的Dispose方法中执行清理逻辑,它们将由垃圾收集器执行非确定性

答案 4 :(得分:2)

另请注意,您需要在析构函数中执行任何操作很少。通常情况下,垃圾收集器都会处理所有事情。例如,在代码中,您不需要在_font的析构函数中部署OwnerDrawnPanel对象。由于GC正在清理面板,因此_font也是如此,因为面板是唯一引用它的人,对吗?

通常,如果您拥有一次性对象,则只需在调用自己的Dispose方法时将其丢弃。但析构函数中的 NOT 。当你的析构函数运行时,你可以打赌所有的聚合对象也都被清理了。

答案 5 :(得分:2)

你几乎不需要使用终结器。它们仅适用于直接包含非托管资源的类,而在.NET 2.0+中,它们应该包含在SafeHandle中。

答案 6 :(得分:2)

我认为Dispose(true)将释放托管和非托管资源,因为我们不需要再次调用finalize,这就是我们在GC.SupressFinalize()之后编写Dispose(true)的原因。

我们在析构函数中调用Dispose(false)来释放非托管资源,并且将由运行时而不是用户代码调用。

答案 7 :(得分:1)

同意Kumar,Dispose(bool disposing)模式也记录在案on MSDN。区别不在托管和非托管资源之间,而是代码或运行时是否调用Dispose

答案 8 :(得分:0)

我发现了一篇关于正确实现IDispose接口的好文章:http://msdn.microsoft.com/en-us/library/ms244737(v=vs.80).aspx

答案 9 :(得分:0)

实施公开public void Dispose()protected virtual void Dispose(bool)~ClassName()终结器的模式是最佳做法recommended by Microsoft,可以整齐地整理托管和清除代码非托管资源。

基本上,使用Disposable的代码应该调用Dispose(),但如果没有,则终结符~ClassName()将被Garbage调用使用集合,并根据其中的哪一个,将参数设置为Dispose(bool)为true或false,在Dispose(bool)中,只有在参数为true时才清理托管资源。

您收到的警告似乎特别建议您在finalize方法~ClassName()中使用此练习。