我找不到它的引用,但我记得读过在析构函数或IDisposable的Dispose()方法中调用虚拟(多态)方法不是一个好主意.
这是真的,如果是这样,有人可以解释为什么吗?
从终结器调用虚拟方法/ 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(); } }
这是Dispose和类型对象时发生的事情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,你开发的公司的Ultra-Junior开发人员C
,被指派编写D
,以一种能够检测到错误的方式编写它,或者base.Dispose(disposing)
在正确的位置进行调用吗?
我不是说你应该永远,永远编写调用从配置一个虚拟方法的代码,只是你需要记录虚拟方法的要求,它从来没有使用在以下派生的任何类定义的任何状态C
.