我有一个工厂方法,用于构建实现IDisposable
的对象。最终,是调用者管理所创建对象的生存期。这种设计引发了一堆CA2000错误。我的设计中是否存在根本错误,是否需要重构,或者只是对静态代码分析警告过于兴奋?
工厂方法
public static DisposableType BuildTheDisposableType(string param1, int param2)
{
var theDisposable = new DisposableType();
// Do some work to setup theDisposable
return theDisposable
}
呼叫者
using(var dt = FactoryClass.BuildTheDisposableType("data", 4))
{
// use dt
}
您应该将其存储到本地变量中,并将初始化封装在try-catch rethrow块中,以防出现任何异常:
public MyDisposable CreateDisposable()
{
var myDisposable = new MyDisposable();
try
{
// Additional initialization here which may throw exceptions.
ThrowException();
}
catch
{
// If an exception occurred, then this is the last chance to
// dispose before the object goes out of scope.
myDisposable.Dispose();
throw;
}
return myDisposable;
}
当Dispose
不会被称为时,尽量不要让一次性对象容易受到异常的攻击
PS:之前有人提到要在finally内部进行处理-这显然是错误的-在非异常路径中,您不想调用Dispose
我建议您在每个单独的工厂方法上,或者在包含它们的整个类上抑制CA2000警告(但前提是这是该类的唯一函数)。
我进一步建议你包括一个理由:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability",
"CA2000:Dispose objects before losing scope",
Justification = "This is a factory method. Caller must dispose")]
您收到错误是因为一次性对象的创建者没有管理它。然而,设计没有根本问题。您只是依靠消费者来利用using
。例如,与当前的ADO对象没有太大区别。
另一种选择是将工厂方法更改为"配置"方法,并将创建一次性对象的责任交给客户端。示例:
public void SetupDisosableThing(IDisposable foo)
{
foo.Bar = "baz";
}
void Main()
{
using (var x = new Thing())
{
SetupDisposableThing(x);
}
}