2

微软建议的dispose 模式说 Dispose() 和 finalizer 都应该调用虚拟的第三个方法 Dispose(bool)。所以它看起来像这样:

public class DisposeBase : IDisposable
{
    private bool _Disposed = false;

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

    ~DisposeBase()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_Disposed)
        {
            if (disposing)
            {
                /* Get rid of managed resources */
            }

            /* Get rid of unmanaged resources */

            _Disposed = true;
        }
    }
}

派生类将覆盖 Dispose(bool)。我想像这样重组它:

public abstract class ExtendableResourceHandlerBase : IDisposable
{
    private bool _Disposed = false;

    /* private resources managed and unmanaged */

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

    ~DisposeBase()
    {
        Dispose(false);
    }

    private void Dispose(bool disposing)
    {
        if (!_Disposed)
        {
            if (disposing)
            {
                ManagedDispose();

                // Dispose of own managed resources
            }

            UnmanagedDispose();

            // Dispose of own unmanged resources

            _Disposed = true;
        }
    }

    protected abstract void ManagedDispose();

    protected abstract void UnmanagedDispose();

    protected abstract xxx ExtendMe(....)

    // other member functionality
}

我正在考虑在框架中声明一个抽象基类的场景,该基类提供一个接口和一些实现获取需要处理的资源 - 因此是IDisposable接口。现在扩展这个基类的客户将被迫考虑如何处置他们的托管和非托管资源。在微软建议的模式的情况下,人们可能会忘记它。请把这个名字想象ExtendableResourceHandlerBase成一个占位符。

在我看来,这将使从 DisposeBase 派生的客户更容易实现他们的 dispose 方法。正如另一个问题的答案所示,其他人也这么认为。我能想到微软的好人为什么要像现在这样构建他们的模式的唯一原因是不分开对托管和非托管资源的处置。还有其他原因吗?非常感谢您启发我。

4

1 回答 1

5

当 Microsoft 记录并推荐该Dispose模式时,预计实现的类IDisposable通常会在其中清理一组资源,Dispose并在其中清理一组较小的资源Finalize;该模式是围绕这一期望设计的。Finalize实际上,除了记录调用失败之外的任何目的,唯一应该覆盖的类Dispose是那些直接继承自Object. 如果其父类未覆盖的派生类Finalize将使用应在终结器中清理的非托管资源,则不应覆盖Finalize它本身也不直接持有非托管资源,而是将资源封装在专用于该目的的类的实例中。这将有助于避免许多奇怪和棘手的边缘情况,否则这些情况可能会随着对象的最终确定而出现,这些对象混合了托管和非托管资源。

让接口方法简单地链接到虚拟方法是一个好主意,即使该protected void Dispose(bool)方法永远不会被调用,其参数不是true. 如果受保护的虚拟方法通过名称而不是无用的参数来区分,则该模式可能会更简洁一些,但是有足够多的人期望 Microsoft 模式即使它并不完美,也可以使用它。

于 2013-08-05T21:18:43.283 回答