使用实现IDisposable
的对象时,常见的模式是;
using(ManagementObject mObj = new ManagementObject())
{
//Work with mObj
}
但是,在System.Management.ManagementObject
的情况下,IDisposable
已在最终父类上声明,在本例中为System.ComponentModel.Component
Dispose
已实现如下(使用ILSpy提取):
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
然而,Dispose
上的 ManagementObject
已实施如下:
// System.Management.ManagementObject
/// <summary>Releases all resources used by the Component.</summary>
public new void Dispose()
{
if (this.wmiClass != null)
{
this.wmiClass.Dispose();
this.wmiClass = null;
}
base.Dispose();
GC.SuppressFinalize(this);
}
似乎在using
块完成时,从直接实现接口的类调用Dispose
;那是System.Component
,因此此时不会清除wmiClass
字段,因为此实现未执行。
如果我用简单的层次结构重新创建它:
public class Parent, IDisposable {
public void Dispose(){
System.WriteLine("Parent Disposing");
}
}
public class Child : Parent {
public new void Dispose()
{
System.WriteLine("Child Disposing");
base.Dispose();
}
}
并编写一个小型测试程序;
using (Child child = new Child())
{
System.WriteLine("Do Stuff");
}
我得到了输出:Do Stuff, Parent Disposing
通常情况下,如果我们希望继承按预期工作,那么在Dispose
和virtual
上将Parent
声明为override
更安全?如果我这样做,我会得到预期事件的顺序与原始示例中发生的事件(如果在直接实现接口的类上调用Dispose,这是有意义的。)
您是否有理由以这种方式实现Dispose而不是基类的虚拟调用?这会强制使用try {} finally {}
模式,您可以在其中显式调用Dispose实现以获得预期结果。