对于引用其他IDisposable对象的类型,我真的需要Basic dispose模式吗?

时间:2017-10-11 15:23:06

标签: c# .net garbage-collection dispose

Microsoft design guidelines提及处理模式和方案如何使用它:

  

在包含实例的类型上实现Basic Dispose Pattern   一次性类型。有关详细信息,请参阅基本处理模式部分   关于基本模式。

稍后,它们显示基本处理模式如下:

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. 如果只有一个参数为true的调用,为什么我们需要实现Dispose(bool)?它可以很容易地简化为无参数Dispose() {resource?.Dispose();}。注意我们这里不需要终结器,因为我们引用的对象是管理的,并且有自己的终结器,所以它们不会被泄露。
  2. 为什么他们建议在没有终结器的情况下拨打GC.SuppressFinalize(this)? GC无论如何都不会调用终结器,因为它不存在!
  3. 我认为需要Dispose(bool)的唯一情况是我们确实有一些非托管引用,它们不实现IDisposable或finalizer(如this article中所示)。但是bool disposing的含义是bool includingManagedResources。那么为什么它被命名为误导“处置”它应该做的事情呢?

1 个答案:

答案 0 :(得分:1)

  1. 其他类可以从您的类继承。考虑到派生类还包含非托管资源(推荐或不推荐),此类应该添加调用Dispose(false)的终结器。如果你的课程被密封了,我会同意你的意见。

  2. 因为方法void Dispose()不应该遵循Microsoft的指导原则virtual,因此派生类将无法在处置后抑制最终确定。您的实现可能不需要终结器,但可能派生类。

  3. 在我看来,它被称为disposing没有特别的原因。我个人也会重命名它。

  4. 无论如何,从我的观点来看,混合拥有托管和非托管资源并不是一个好方法。正如评论中已经提到的,即使Microsoft建议将非托管资源封装到托管资源中,因此您需要实现终结器的情况可能很少见。我不记得我最后一次这样做了。

    由于多种原因,例如误导性命名或因为难以理解,我也没有坚持指南的实施。另一种方法是this answer