我真的需要基本的配置模式来引用其他IDisposable对象吗?

问题描述:

Microsoft design guidelines提Dispose模式和场景如何使用它:我真的需要基本的配置模式来引用其他IDisposable对象吗?

国家执行含一次性类型的 实例类型基本Dispose模式。有关基本模式的详细信息,请参阅基本处理模式部分 。

后来,他们表现出基本的Dispose模式如下:

public class DisposableResourceHolder : IDisposable { 

    private SafeHandle resource; // handle to a resource 

    public DisposableResourceHolder(){ 
     this.resource = ... // allocates the resource 
    } 

    public void Dispose(){ 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing){ 
     if (disposing){ 
      if (resource!= null) resource.Dispose(); 
     } 
    } 
} 

问题是:

  1. 为什么我们需要实现Dispose(布尔)如果它只是一个带有参数true的单个调用?它可以很容易地简化为仅仅无参数Dispose() {resource?.Dispose();}。注意我们不需要终结器,因为我们所引用的对象是被管理的并且有自己的终结器,所以它们不会被泄漏。
  2. 为什么他们建议拨打GC.SuppressFinalize(this)而没有终结者?无论如何,GC不会调用终结器,因为它不存在!
  3. 当我看到Dispose(bool)的需要时,唯一的情况是我们确实有一些非托管引用,它没有实现IDisposable或终结器(如this article所示)。但那么bool disposing的含义就是bool includingManagedResources。那么为什么它被命名为“处置”其实际上应该做的事情?
+1

你没有。微软担心这些事情,因为他们编写了有终结器的类。永远不要写你自己的终结者。微软也花了一段时间才发现,然后他们创建了SafeHandle类。 –

+1

这种模式背后的原因是可以从你的类继承而来,并且这个继承的类可能有终结器。不 - 你不需要这样做。 – Evk

+0

@Evk真的有道理......谢谢! –

  1. 其他类可以从你的类继承。考虑到派生类也拥有非托管资源(建议与否),此类应添加终结器调用Dispose(false)。如果你的班级封闭了,我会同意你的意见。

  2. 因为方法void Dispose()不应该是virtual遵循Microsoft的指导方针,因此派生类将无法在处置后禁止终结。你的实现可能不需要终结器,但可能派生类。

  3. 在我看来,没有具体的原因叫做disposing。我个人也会重命名它。

无论如何,从我的角度来看,混合拥有托管和非托管资源并不是一个好方法。正如评论中已经提到的,微软建议将非托管资源封装到托管资源中,因此您需要实现终结器的情况可能很少。我不记得自己最后一次做这件事的时间。

我也不会坚持从指导方针的实施,因为多种原因,如误导性的命名或难以理解。另一种方法是this answer

+0

第2项需要[需要引用]。我唯一能找到它的地方是,只有当类实现了Disposable模式时,它才应该是虚拟的。 –

+0

@HansPassant最初链接的文档已经声明“不要使无参数Dispose方法为虚拟。”。编辑:我想我现在理解你的评论。当然不禁止编写虚拟处置方法。对于参考文档而言,这不是推荐的方式。我添加的另一种方法,不符合本指南,它的做法有所不同。 – Peit

+0

对,它只是一次性模式的明智建议,Dispose(布尔)已经是虚拟的。当你不使用这个模式时,这很好。并建议除非你声明课程密封。 –