Kit*_*Kit 2 c# dispose idisposable finalizer boilerplate
我不是样板代码的粉丝:复制粘贴重用可能容易出错.即使您使用代码段或智能模板,也无法保证其他开发人员所做的,这意味着无法保证他们做得对.而且,如果你必须看到代码,你必须理解和/或维护它.
我想从社区中了解到:我对类层次结构的IDispose的实现是否是"传统"处置模式的合法替代?通过合法,我的意思是正确,相当好的表现,健壮和可维护.
我很好,这个替代方案是完全错误的,但如果是,我想知道为什么.
此实现假定您可以完全控制类层次结构; 如果你不这样做,你可能不得不回到样板代码.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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个"完整"实现,在某种意义上我提供了对最终化的支持(知道大多数实现不需要终结器),检查对象是否被丢弃等等.真正的实现可能会删除终结器,例如,或者创建一个包含终结器的DisposableObject的子类.基本上,我把所有我能想到的东西扔进了这个问题.
可能有一些我已经错过的边缘情况和深奥的情况,所以我邀请任何人在这种方法中挖洞或用纠正来支撑它.
其他替代方案可能是在DisposableObject中使用单个Queue <Disposer>处理器而不是两个列表; 在这种情况下,当调用处理器时,它们将从列表中删除.我可以想到其他一些细微的变化,但它们具有相同的一般结果:没有样板代码.
您可能遇到的第一个问题是C#只允许您从单个基类继承,在这种情况下,它始终是DisposableObject.在这里,您通过强制其他层来混乱您的类层次结构,以便需要继承的类DisposableObject和其他一些对象可以这样做.
您还将通过此实现引入大量的开销和维护问题(更不用说每当有新的项目出现时重复的培训成本,您必须解释他们应该如何使用此实现而不是定义的模式) .你知道有多个状态可以跟踪你的两个列表,没有对动作调用的错误处理,调用动作时的语法看起来很"奇怪"(虽然调用数组中的方法可能很常见,在数组访问之后简单地放置()的语法看起来很奇怪).
我理解减少你必须编写的样板数量的愿望,但可处置性通常不是我建议采用捷径或偏离模式的那些领域之一.我通常得到的最接近的是使用辅助方法(或扩展方法)将实际调用包装到Dispose()给定对象上.这些调用通常如下所示:
if (someObject != null)
{
someObject.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
这可以使用辅助方法简化,但请记住,FxCop(或任何其他检查正确的dispose实现的静态分析工具)会抱怨.
就性能而言,请记住,您正在使用此类实现进行大量委托调用.就委托人而言,这比普通的方法调用要贵一些.
可维护性肯定是一个问题.正如我所提到的,每当有新的项目进入项目时,您就会有重复的培训成本,并且您必须解释他们应该如何使用此实现而不是定义的模式.不仅如此,每个人都记得将一次性对象添加到列表中时遇到问题.
总的来说,我认为这样做是一个坏主意,会导致很多问题,特别是随着项目和团队规模的增加.
| 归档时间: |
|
| 查看次数: |
908 次 |
| 最近记录: |