微软处置模式结构的原因是什么?

时间:2013-08-05 20:15:04

标签: c# design-patterns idisposable

来自Microsoft的建议dispose pattern说Dispose()和终结器都应该调用虚拟的第三种方法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方法。而another question的答案显示,其他人也这么认为。我可以想到为什么微软的好人建立他们现在的模式的唯一原因不是分割托管和非托管资源的处置。还有其他原因吗?非常感谢你的启发。

1 个答案:

答案 0 :(得分:5)

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

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