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

标签 c# .net dispose

<分区>

我知道实现 dispose pattern 的一般准则警告不要实现虚拟 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();
    }
}

我发现这比完整的处理模式更具可读性。我知道如果我们将非托管资源引入到 Base 类中,这个示例就会出现问题。但假设这不会发生。上面的例子是有效/安全/稳健的,还是会造成任何问题?我是否应该坚持标准的成熟处理模式,即使没有使用非托管资源?或者在这种情况下,上述方法确实完全可行 - 根据我的经验,这比处理非托管资源要普遍得多?

最佳答案

在我不处理非托管资源的情况下,我已经放弃了成熟的 IDisposable 模式。

我看不出有什么理由不能放弃该模式并使 Dispose 成为虚拟如果您可以确保派生类不会引入非托管资源!

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

首先,在我们只处理托管对象的情况下,拥有终结器将毫无意义:如果从终结器调用 Dispose (Dispose(disposing: false)根据成熟的模式),我们可能无法安全地访问/取消引用其他引用类型的托管对象,因为它们可能已经不存在了。只能安全地访问从正在终结的对象可达的值类型对象。

如果finalizer没有意义,那disposing标志也没有意义,用来区分Dispose是被显式调用还是被调用终结器。

如果没有finalizer,也不需要GC.SuppressFinalize

我什至不确定 Dispose 在仅限托管的情况下是否仍然必须不抛出任何异常。据我所知,此规则的存在主要是为了保护终结器线程。(请参阅@usr 的 comment below。)

如您所见,一旦终结器消失,许多经典的 Disposable 模式就不再需要了。

关于c# - 只要层次结构中的所有类仅使用托管资源,就可以使用虚拟 Dispose() 方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32354386/

相关文章:

c# - 如何以及何时处置 c# 静态成员?

c# - 在 Unity 中增加速度时球会晃动

c# - 根据文件填充一组复选框

c# - SQL将行转换为没有数据透视表的列

.net - 如何在winforms的设计模式下执行代码

.net - 如何禁用ASP.NET Core的IIS Express启动配置文件?

c# - 获取基本 IQueryable 实例的 Count()

vb.net - service.close()与service.abort()-WCF示例

c# - EF7 beta6 : Error saving multiple entities

c# - 在 Windows 窗体中为 Font 调用 dispose()