我真的需要基本的配置模式来引用其他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();
}
}
}
我问题是:
- 为什么我们需要实现Dispose(布尔)如果它只是一个带有参数true的单个调用?它可以很容易地简化为仅仅无参数
Dispose() {resource?.Dispose();}
。注意我们不需要终结器,因为我们所引用的对象是被管理的并且有自己的终结器,所以它们不会被泄漏。 - 为什么他们建议拨打
GC.SuppressFinalize(this)
而没有终结者?无论如何,GC不会调用终结器,因为它不存在! - 当我看到Dispose(bool)的需要时,唯一的情况是我们确实有一些非托管引用,它没有实现IDisposable或终结器(如this article所示)。但那么
bool disposing
的含义就是bool includingManagedResources
。那么为什么它被命名为“处置”其实际上应该做的事情?
其他类可以从你的类继承。考虑到派生类也拥有非托管资源(建议与否),此类应添加终结器调用
Dispose(false)
。如果你的班级封闭了,我会同意你的意见。因为方法
void Dispose()
不应该是virtual
遵循Microsoft的指导方针,因此派生类将无法在处置后禁止终结。你的实现可能不需要终结器,但可能派生类。在我看来,没有具体的原因叫做
disposing
。我个人也会重命名它。
无论如何,从我的角度来看,混合拥有托管和非托管资源并不是一个好方法。正如评论中已经提到的,微软建议将非托管资源封装到托管资源中,因此您需要实现终结器的情况可能很少。我不记得自己最后一次做这件事的时间。
我也不会坚持从指导方针的实施,因为多种原因,如误导性的命名或难以理解。另一种方法是this answer。
第2项需要[需要引用]。我唯一能找到它的地方是,只有当类实现了Disposable模式时,它才应该是虚拟的。 –
@HansPassant最初链接的文档已经声明“不要使无参数Dispose方法为虚拟。”。编辑:我想我现在理解你的评论。当然不禁止编写虚拟处置方法。对于参考文档而言,这不是推荐的方式。我添加的另一种方法,不符合本指南,它的做法有所不同。 – Peit
对,它只是一次性模式的明智建议,Dispose(布尔)已经是虚拟的。当你不使用这个模式时,这很好。并建议除非你声明课程密封。 –
你没有。微软担心这些事情,因为他们编写了有终结器的类。永远不要写你自己的终结者。微软也花了一段时间才发现,然后他们创建了SafeHandle类。 –
这种模式背后的原因是可以从你的类继承而来,并且这个继承的类可能有终结器。不 - 你不需要这样做。 – Evk
@Evk真的有道理......谢谢! –