只要层次结构中的所有类仅使用托管资源,是否可以使用虚拟Dispose()方法?

w12*_*128 5 .net c# dispose

我知道实施配置模式的一般准则警告不要实现虚拟Dispose().但是,大多数情况下,我们只使用类中的托管资源,因此完整的部署模式似乎有点过分 - 即我们不需要终结器.在这种情况下,Dispose()在基类中使用虚拟是否可以?

考虑这个简单的例子:

abstract class Base : IDisposable
{
    private bool disposed = false;
    public SecureString Password { get; set; } // SecureString implements IDisposable.

    public virtual void Dispose()
    {
        if (disposed)
            return;

        if (Password != null)       
            Password.Dispose();     

        disposed = true;
    }
}

class Sub : Base
{
    private bool disposed = false;
    public NetworkStream NStream { get; set; } // NetworkStream implements IDisposable.

    public override void Dispose()
    {   
        if (disposed)
            return;

        if (NStream != null)
            NStream.Dispose();

        disposed = true;
        base.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

我觉得这比完整的配置模式更具可读性.据我所知,如果我们将非托管资源引入Base类中,这个示例将会成为问题.但是假设这不会发生.以上示例是有效/安全/健壮的,还是会造成任何问题?即使没有使用非托管资源,我是否应该坚持标准的完整配置模式?或者上述方法在这种情况下确实完全正常 - 根据我的经验,这比处理非托管资源更常见?

sta*_*ica 5

IDisposable在我没有处理非托管资源的情况下,我已经放弃了完整的模式.

如果你能确保派生类不会引入非托管资源,我看不出你为什么不能放弃模式和Dispose虚拟化的原因!

(这里存在一个问题,因为你不能强制执行这个.你无法控制派生类将添加哪些字段,所以虚拟没有绝对的安全性Dispose.但是即使你使用了完整的模式,派生的也是如此. class可能会出错,因此总有一些信任涉及子类型遵守某些规则.)

首先,在我们只处理托管对象的情况下,使用终结器是没有意义的:如果Dispose 从终结器调用(Dispose(disposing: false)根据完整模式),我们可能无法安全地访问/取消引用其他引用类型的托管对象,因为它们可能已经不见了 只能安全地访问从最终确定的对象可到达的值类型对象.

如果终结器没有意义,那么拥有disposing标志也是没有意义的,该标志用于区分是否Dispose显式调用或是否由终结器调用.

GC.SuppressFinalize 如果没有终结器,也没有必要这样做.

我甚至不确定是否仍然必须Dispose 在仅托管方案中抛出任何异常.AFAIK这个规则主要用于保护终结器线程.(参见下面的 @ usr 评论.)

正如您所看到的,一旦终结器出现,就不再需要大部分经典的Disposable模式.