Sar*_*els 8 c# abstract-class dispose static-analysis
我有一个实现IDisposable的抽象类,如下所示:
public abstract class ConnectionAccessor : IDisposable
{
public abstract void Dispose();
}
Run Code Online (Sandbox Code Playgroud)
在Visual Studio 2008 Team System中,我在项目上运行了代码分析,其中一个警告如下:
Microsoft.Design:修改'ConnectionAccessor.Dispose()'以便它调用Dispose(true),然后在当前对象实例上调用GC.SuppressFinalize(在Visual Basic中为'this'或'Me'),然后返回.
它只是愚蠢,告诉我修改抽象方法的主体,还是应该在任何派生实例中做进一步的事情Dispose?
Pav*_*aev 12
您应该遵循传统的实施模式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
}
}
Run Code Online (Sandbox Code Playgroud)
这里的关键是终结器和Dispose非托管清理之间没有重复,但是任何派生类都可以扩展托管和非托管清理.
对于您的情况,您应该做的是:
protected abstract void Dispose(bool disposing)
Run Code Online (Sandbox Code Playgroud)
并保留其他所有内容.即使这是值得怀疑的,因为你现在正在强制执行你的派生类Dispose- 你怎么知道它们都需要它?如果您的基类没有任何可处置的东西,但是大多数派生类可能会执行(可能有一些例外),那么只需提供一个空实现.这是System.IO.Stream(本身是抽象的)所做的,所以有先例.
dtb*_*dtb 10
警告基本上告诉您在类中实现Dispose模式.
生成的代码应如下所示:
public abstract class ConnectionAccessor : IDisposable
{
~ConnectionAccessor()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这看起来确实有点挑剔,但这个建议是有效的。您已经表明您希望 ConnectionAccessor 的任何子类型都将拥有需要处理的内容。因此,确保基类完成正确的清理(就 GC.SuppressFinalize 调用而言)似乎比依赖每个子类型来完成似乎更好。
我使用 Bruce Wagners 的书《Effective 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;
}
Run Code Online (Sandbox Code Playgroud)