【发布时间】:2009-09-09 01:52:28
【问题描述】:
我不喜欢样板代码:复制粘贴重用可能容易出错。即使您使用代码 sn-ps 或智能模板,也不能保证其他开发人员做到了,这意味着不能保证他们做对了。而且,如果您必须查看代码,则必须理解和/或维护它。
我想从社区中了解的是:我为类层次结构实现的 IDispose 是"traditional" dispose pattern 的合法替代方案吗?我所说的合法是指正确、性能相当不错、健壮且可维护。
我可以接受这种替代方案是完全错误的,但如果是,我想知道原因。
此实现假定您可以完全控制类层次结构;如果你不这样做,你可能不得不求助于样板代码。对 Add*() 的调用通常在构造函数中进行。
public abstract class DisposableObject : IDisposable
{
protected DisposableObject()
{}
protected DisposableObject(Action managedDisposer)
{
AddDisposers(managedDisposer, null);
}
protected DisposableObject(Action managedDisposer, Action unmanagedDisposer)
{
AddDisposers(managedDisposer, unmanagedDisposer);
}
public bool IsDisposed
{
get { return disposeIndex == -1; }
}
public void CheckDisposed()
{
if (IsDisposed)
throw new ObjectDisposedException("This instance is disposed.");
}
protected void AddDisposers(Action managedDisposer, Action unmanagedDisposer)
{
managedDisposers.Add(managedDisposer);
unmanagedDisposers.Add(unmanagedDisposer);
disposeIndex++;
}
protected void AddManagedDisposer(Action managedDisposer)
{
AddDisposers(managedDisposer, null);
}
protected void AddUnmanagedDisposer(Action unmanagedDisposer)
{
AddDisposers(null, unmanagedDisposer);
}
public void Dispose()
{
if (disposeIndex != -1)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
~DisposableObject()
{
if (disposeIndex != -1)
Dispose(false);
}
private void Dispose(bool disposing)
{
for (; disposeIndex != -1; --disposeIndex)
{
if (disposing)
if (managedDisposers[disposeIndex] != null)
managedDisposers[disposeIndex]();
if (unmanagedDisposers[disposeIndex] != null)
unmanagedDisposers[disposeIndex]();
}
}
private readonly IList<Action> managedDisposers = new List<Action>();
private readonly IList<Action> unmanagedDisposers = new List<Action>();
private int disposeIndex = -1;
}
从某种意义上说,这是一个“完整”的实现,我支持终结器(知道大多数实现不需要终结器)、检查对象是否被释放等。真正的实现可能会移除终结器,例如,或创建一个包含终结器的 DisposableObject 子类。基本上,我只是为了这个问题把我能想到的所有东西都扔了。
我可能错过了一些边缘情况和深奥的情况,所以我邀请任何人在这种方法中戳漏洞或通过更正来支持它。
其他选择可能是在 DisposableObject 中使用单个 Queue
【问题讨论】:
-
这仍然受到这样一个事实的影响,即实现者必须记住为聚合类型调用 Add() 方法。就个人而言,我认为这与通常的模式相比没有任何好处。
-
别这样。使用所写的 Dispose 模式。有经验的开发人员会一眼看懂代码,你会覆盖所有的基础,FxCop 等工具可以帮助验证它,你可以编写 sn-ps 来准确地实现它,你会遵守微软的标准。 bluebytesoftware.com/blog/…
-
顺便说一句,如果你想要的是 DisposableCollection
,你应该能够找到它的许多实现。 -
好的,我刚刚意识到至少存在一个问题。如果 unmanagedDisposer 抛出,则不会运行任何“基本”处理程序。这在传统模式中不会发生,因为基本终结器将始终运行。
-
这个问题几乎完全一样:stackoverflow.com/questions/874764/…
标签: c# dispose idisposable finalizer boilerplate