【问题标题】:Do I really need Basic dispose pattern for type referencing other IDisposable objects?我真的需要 Basic dispose 模式来引用其他 IDisposable 对象吗?
【发布时间】:2018-03-23 08:32:35
【问题描述】:

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

【问题讨论】:

  • 你没有。微软担心这些事情,因为他们编写了具有终结器的类。永远不要编写自己的终结器。微软也花了一段时间才发现这一点,然后他们创建了 SafeHandle 类。
  • 这种模式背后的原因是可以从您的类继承,并且该继承的类可能具有终结器。不 - 你不需要这样做。
  • @Evk 这实际上是有道理的......谢谢!

标签: c# .net garbage-collection dispose


【解决方案1】:
  1. 其他类可以从您的类继承。考虑到派生类也包含非托管资源(推荐与否),该类应添加调用Dispose(false) 的终结器。如果你的课程是密封的,我会同意你的。

  2. 因为方法 void Dispose() 不应该是 virtual 遵循 Microsoft 的指导方针,因此派生类将没有机会在处置后抑制终结。您的实现可能不需要终结器,但派生类可能需要。

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

无论如何,在我看来,混合拥有托管和非托管资源并不是一个好方法。正如评论中已经提到的,甚至 Microsoft 建议将非托管资源封装到托管资源中,因此您需要实现终结器的情况可能很少见。我不记得上次我自己这样做是什么时候了。

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

【讨论】:

  • 第 2 项需要 [需要引用]。我唯一能发现它不应该是虚拟的,只有当类实现了 Disposable 模式。
  • @HansPassant 最初链接的文档已经声明“不要将无参数的 Dispose 方法设为虚拟。”。编辑:我想我现在明白你的评论了。当然不禁止写一个虚拟的 dispose 方法。就参考文档而言,这不是推荐的方式。我添加的替代方法不遵守本指南,但效果不同。
  • 对,这只是对一次性模式的明智建议,Dispose(bool) 已经是虚拟的。当您不使用该模式时,这很好。除非你声明类是密封的,否则建议使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 2011-03-31
  • 1970-01-01
  • 2010-10-14
  • 2012-04-19
  • 1970-01-01
  • 2021-06-12
相关资源
最近更新 更多