我找不到对它的引用,但我记得读过,在析构函数中调用虚拟(多态)方法或IDisposable的Dispose()方法不是一个好主意。

这是真的吗?如果可以,有人可以解释为什么吗?

最佳答案

出于相同的原因,从finalizer / Dispose调用虚拟方法是不安全的。无法确保派生类尚未清除虚拟方法正确执行所需的某些状态。

有些人对标准Disposable模式及其对虚拟方法virtual Dispose(bool disposing)的使用感到困惑,并认为这可以在处理过程中使用任何虚拟方法。考虑以下代码:

class C : IDisposable {
    private IDisposable.Dispose() {
        this.Dispose(true);
    }
    protected virtual Dispose(bool disposing) {
        this.DoSomething();
    }

    protected virtual void DoSomething() {  }
}
class D : C {
    IDisposable X;

    protected override Dispose(bool disposing) {
        X.Dispose();
        base.Dispose(disposing);
    }

    protected override void DoSomething() {
        X.Whatever();
    }
}

这是当您处理和释放类型为D的对象d时发生的情况:
  • 一些代码调用((IDisposable)d).Dispose()
  • C.IDisposable.Dispose()调用虚拟方法D.Dispose(bool)
  • D.Dispose(bool)处理D.X
  • D.Dispose(bool)静态调用C.Dispose(bool) (在编译时已知调用的目标)
  • C.Dispose(bool)调用虚拟方法D.DoSomething()
  • D.DoSomething在已处置的D.X.Whatever()上调用D.X方法

  • 现在,大多数运行此代码的人都会做一件事来修复它-在清理自己的对象之前,他们将base.Dispose(dispose)调用移至。而且,是的,确实有效。但是,您是否真的信任程序员X,您开发C的公司的特级开发人员,分配给它编写D,以一种可以检测到错误的方式编写base.Dispose(disposing),或者将C调用在正确的位置?

    我并不是说您永远都不要永远编写调用Dispose中的虚拟方法的代码,只是您需要文档要求虚拟方法永远不要使用在ojit_code下衍生的任何类中定义的任何状态。

    关于.net - 可以从Dispose或析构函数调用虚拟方法吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/137621/

    10-17 01:13