从这些简单的类开始...
假设我有一组像这样的简单类:
class Bus
{
Driver busDriver = new Driver();
}
class Driver
{
Shoe[] shoes = { new Shoe(), new Shoe() };
}
class Shoe
{
Shoelace lace = new Shoelace();
}
class Shoelace
{
bool tied = false;
}
一辆 Bus
有一个 Driver
,Driver
有两只 Shoe
,每个 Shoe
有一个 Shoelace
。这都很傻。
向 Shoelace 添加 IDisposable 对象
后来我决定对 Shoelace
进行某些操作时可以使用多线程,因此我添加了一个 EventWaitHandle
用于线程间通信。现在 Shoelace
如下:
class Shoelace
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
// ... other stuff ..
}
在Shoelace中实现IDisposable
但是现在Microsoft的FxCop会抱怨:"在'Shoelace'上实现IDisposable,因为它创建了以下IDisposable类型的成员:'EventWaitHandle'"。
好吧,我在Shoelace
上实现了IDisposable
,我的整洁小类变成了这个可怕的混乱:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Shoelace()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
}
// No unmanaged resources to release otherwise they'd go here.
}
disposed = true;
}
}
正如评论者所指出的,由于Shoelace
本身没有非托管资源,因此我可以使用更简单的dispose实现而无需使用Dispose(bool)
和析构函数:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
public void Dispose()
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
GC.SuppressFinalize(this);
}
}
观看IDisposable的可怕传播
好了,这个问题得到解决。但是现在FxCop会抱怨Shoe
创建Shoelace
,所以Shoe
也必须成为IDisposable
。
而且Driver
创建Shoe
,所以Driver
也必须成为IDisposable
。
Bus
创建Driver
,所以Bus
也必须成为IDisposable
,以此类推。
突然间,我对Shoelace
做出的小改变就让我需要做很多工作,我的老板也在想为什么我需要检查Bus
来修改Shoelace
。
问题
如何防止IDisposable
的传播,但仍确保您的非托管对象得到正确释放?