C# 抽象 Dispose 方法
-
19-09-2019 - |
题
我有一个实现 IDisposable 的抽象类,如下所示:
public abstract class ConnectionAccessor : IDisposable
{
public abstract void Dispose();
}
在 Visual Studio 2008 Team System 中,我对项目运行了代码分析,出现的警告之一如下:
微软设计:修改“ConnectionAccessor.Dispose()”,使其调用 Dispose(true),然后对当前对象实例(Visual Basic 中的“this”或“Me”)调用 GC.SuppressFinalize,然后返回。
告诉我修改抽象方法的主体是否只是愚蠢,或者我应该在任何派生实例中做进一步的事情 Dispose
?
解决方案
您应该遵循用于实现Dispose
常规图案。制作Dispose()
虚拟被认为是不好的做法,因为传统模式强调的代码重用在“管理清理”(API客户端呼叫Dispose()
直接或通过using
)和“非托管清理”(GC呼吁终结)。提醒,该图案是这样的:
public class Base
{
~Base()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // so that Dispose(false) isn't called later
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Dispose all owned managed objects
}
// Release unmanaged resources
}
}
这里重点是,有对于非托管清理终结和Dispose
之间没有重复,并且还没有任何派生类可以延伸托管和非托管清理。
有关你的情况,你应该做的是这样的:
protected abstract void Dispose(bool disposing)
和离开一切不变。即使是可疑的价值,因为你执行你的派生类,现在实施Dispose
- 你怎么知道,所有的人都需要它吗?如果你的基类有什么处置,但大多数派生类可能做(除了少数例外,也许),然后只需提供空的实现。它是什么System.IO.Stream
(本身抽象)确实,所以已有先例。
其他提示
在警告主要是告诉你实现 Dispose模式 在你的类。
将所得的代码应该是这样的:
public abstract class ConnectionAccessor : IDisposable
{
~ConnectionAccessor()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
我对迄今为止提供的答案的唯一抱怨是他们都假设你 需要 有一个终结器,但情况不一定如此。与终结相关的性能开销相当大,如果没有必要,我不想将其强加于我的所有派生类。
看 这篇博文 作者:Joe Duffy,它解释了您何时可能需要或不需要终结器,以及在任何一种情况下如何正确实现 Dispose 模式。
总结 Joe 的博客文章,除非您正在做一些相当低级的处理非托管内存的事情,否则您不应该实现终结器。作为一般经验法则,如果您的类仅保存对本身实现 IDisposable 的托管类型的引用,则不需要终结器(但应该实现 IDisposable 并处置这些资源)。如果您直接从代码分配非托管资源(PInvoke?)并且必须释放这些资源,那么您需要一个。如果派生类确实需要,则始终可以添加终结器,但是通过将其放入基类来强制所有派生类具有终结器会导致所有派生类受到可终结对象的性能影响,而这种开销可能不会增加。必要的。
虽然它似乎有点像吹毛求疵,建议是有效的。您已经表明您期待任何的子类型ConnectionAccessor将有的东西的,他们需要处理。因此,它似乎更好,以确保正确的清除完成(在GC.SuppressFinalize呼叫而言)由基类而不是依赖于每种亚型做到这一点。
我用在布鲁斯瓦格纳书有效的C#提到的处置图案,其基本上是:
public class BaseClass : IDisposable
{
private bool _disposed = false;
~BaseClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
//release managed resources
}
//release unmanaged resources
_disposed = true;
}
}
public void Derived : BaseClass
{
private bool _disposed = false;
protected override void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
//release managed resources
}
//release unmanaged resources
base.Dispose(disposing);
_disposed = true;
}
该警告是有趣虽然。埃里克利珀,C#的设计者之一,博客上讲述为什么错误信息应该是“诊断但不规范:说明问题,而不是解决方案”。 读到这里。