应该将IDisposable::Dispose()设置为虚方法吗?

15 浏览
0 Comments

应该将IDisposable::Dispose()设置为虚方法吗?

有一个SomeDisposable工厂实际上创建/返回了一种看门狗包装器。\n

public class Wrapper : SomeDisposable
{
    public new /*:(*/ Dispose() { ... };
}

\n调用者使用方式如下:\n

using (SomeDisposable sd = SomeDisposableFactory.Create(...))
{
} // Wrapper.Dispose() 没有被调用。

\nWrapper.Dispose()从未被调用。如果Dispose()是虚拟的,那么Wrapper.Dispose()会被调用。\nIDisposable接口不能保证另一个最佳实践方法virtual Dispose(bool)实际上存在,也不能强制它们都是虚拟的,因此不能普遍依赖它的存在(它只是一种推荐的模式)。接口目前不允许对虚拟方法进行约束。\n不将推荐的Dispose()模式设为虚拟的,这样做有什么优缺点呢?C#应该允许通过接口强制使用虚拟方法吗(因为抽象类作为契约定义并不流行)?

0
0 Comments

在这段内容中,提到了一个关于“Should IDisposable::Dispose() be virtual”的问题。这个问题的出现是因为在使用IDisposable接口时,有些人认为Dispose()方法应该是virtual的,而有些人则认为不需要。

为了解决这个问题,应该使用通用的“dispose模式”,代码如下:

public class DisposableResourceHolder : IDisposable
{
    private SafeHandle resource; // handle to a resource
    public DisposableResourceHolder()
    {
        this.resource = ... // allocates the resource
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // dispose managed resources.
            if (resource != null) resource.Dispose();
        }
        // free unmanaged resources.
    }
}

在这段代码中,DisposableResourceHolder类实现了IDisposable接口,并使用了通用的“dispose模式”。这个模式包括了一个Dispose()方法和一个Dispose(bool disposing)方法。在Dispose()方法中,调用了Dispose(bool disposing)方法,然后调用了GC.SuppressFinalize(this)方法来禁止对象的finalizer被调用。在Dispose(bool disposing)方法中,释放了托管资源并释放了非托管资源。

在讨论中,某些情况下了使用finalizer的问题。他们认为只有在类拥有非托管资源时才应该使用finalizer。添加了finalizer之后,对象会成为一个长生命周期对象,并且至少会被提升为一代对象。另外,如果有需要,派生类总是可以定义自己的finalizer。

有人问到为什么要实现IDisposable接口如果没有非托管资源。这时,有人解释了托管资源的概念,例如数据库连接等。finalizer的作用是确保在没有调用Dispose()方法的情况下清理非托管资源。因此,在Dispose()方法中调用GC.SuppressFinalize()方法可以表明已经调用了Dispose()方法并清理了资源。

还某些情况下了GC.SuppressFinalize()方法的使用问题。他们认为这个方法可能不是必需的,因为只有从System.Object直接派生的类才应该定义清理finalizer。但在某些情况下,可能需要确保Dispose()方法的调用不会被优化掉,可以使用GC.KeepAlive(this)来实现,而GC.SuppressFinalize(this)也可以达到同样的效果。

这篇文章讨论了IDisposable::Dispose()方法是否应该是virtual的问题,并给出了使用通用“dispose模式”的解决方法。同时还涉及到了使用finalizer的问题以及GC.SuppressFinalize()方法的使用问题。

0
0 Comments

IDisposable::Dispose()方法是否应该是虚拟的?

在这个问题中,出现了这样的情况:Dispose()方法(非虚拟)应该调用一个protected virtual void Dispose(bool)方法。这样可以确保基类的Dispose调用可以正确地传递到上层继承。

这在IDisposable的文档中有明确说明:

- 它应该提供一个public的非虚拟Dispose()方法和一个protected virtual Dispose(Boolean disposing)方法。

- Dispose()方法必须调用Dispose(true),并且应该为了性能而禁用终结器。

- 基类不应包含任何终结器。

接受这个答案,同时也希望C#本身能够规定和强制执行这些“应该”和“必须”的规定。

根据上述内容,我们可以总结出如下问题的原因和解决方法:IDisposable::Dispose()方法应该是虚拟的,因为这样可以确保在继承层级中正确调用基类的Dispose方法。而根据IDisposable的文档,我们可以通过在基类中提供一个protected virtual Dispose(Boolean disposing)方法来实现这一点。这样一来,基类的Dispose方法就可以在子类中被正确地调用和实现。希望C#能够在语言级别上规定和强制执行这些规定,以提高代码的可读性和维护性。

0