C#中调用Dispose(IsDisposing)模式的目的是什么?

9

这里是来自MSDN的代码。我不明白为什么不在常规的Dispose()方法中完成工作。那么有了Dispose(bool)方法的目的是什么?谁会在这里调用Dispose(false)呢?

public void Dispose() 
{
    Dispose(true);

    // Use SupressFinalize in case a subclass
    // of this type implements a finalizer.
    GC.SuppressFinalize(this);      
}

protected virtual void Dispose(bool disposing)
{
    // If you need thread safety, use a lock around these 
    // operations, as well as in your methods that use the resource.
    if (!_disposed)
    {
        if (disposing) {
            if (_resource != null)
                _resource.Dispose();
                Console.WriteLine("Object disposed.");
        }

        // Indicate that the instance has been disposed.
        _resource = null;
        _disposed = true;   
    }
}
4个回答

16

最终处理程序将调用Dispose(false) - 在这种情况下,您不会触及任何其他托管资源(可能已经被终结)。

个人而言,我很少按照这种模式进行编写 - 因为我几乎从不需要使用最终处理程序,而且很少编写非密封的IDisposable实现。如果您正在编写没有最终处理程序的密封类,则可以采用简单的实现。


1
如果你在一个非密封类中封装了一个IDisposable资源,你仍然应该遵循这种模式,以便子类可以得到适当且一致的处理。 - Reed Copsey
即使不需要使用终结器。 - Reed Copsey
@Reed:只有当涉及到子类时,才有必要这样做,这样它们就可以拥有finalizers——否则为什么要使用一个始终为true的参数呢? - Jon Skeet
1
对于“我不遵循这种模式”的+1,如果您有Win32句柄或类似的内容,则它非常有用,但是如果没有终结器,那么它是不必要的。 - csharptest.net
1
@Jon:没错,但是为了给你的子类提供一个虚拟的Dispose()方法,你需要更改名称(因为你不能同时拥有受保护的虚拟Dispose和Dispose,除非你显式实现Dispose)- 但无论如何,这将是一个非标准的实现,你的子类将处理它。为什么不直接提供他们预期的内容呢? - Reed Copsey
@Reed:仅使用公共虚拟Dispose()方法有什么问题吗? - Jon Skeet

3

1
关于答案,
引用:
您的Dispose(disposing)方法不应在从终结器调用时显式释放资源,因为这些资源可能已经被GC释放。
缺少一个重要的单词。实际上应该是这样说:
您的Dispose(disposing)方法不应在从终结器调用时显式释放可终结(即托管)资源,因为这些资源可能已经被GC释放。只有本机资源应该在终结器中释放。
我相信发帖人的意思是这个,只是在帖子中没有明确表述:)

0

如果从终结器中调用Dispose(disposing)方法,那么您的方法不应该显式地释放资源,因为这些资源可能已经被垃圾回收器释放了。

因此,Dispose(disposing)应该检查它是手动调用还是从垃圾回收器调用,并采取相应的措施。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接