17

我有一个工厂方法来构建实现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
}    
4

4 回答 4

19

您应该将其存储到局部变量中,并将初始化包装在 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

于 2015-08-21T00:17:00.807 回答
10

我建议您在每个单独的工厂方法或包含它们的整个类上禁止 CA2000 警告(但前提是这是该类的唯一功能)。

我进一步建议你包括一个理由:

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability",
    "CA2000:Dispose objects before losing scope",
    Justification = "This is a factory method. Caller must dispose")]
于 2013-12-06T20:17:23.510 回答
2

您收到错误是因为一次性对象的创建者没有管理它。但是,设计并没有根本性的错误。你只是依靠消费者来利用using。例如,与当前的 ADO 对象没有太大区别。

于 2013-12-06T20:10:41.113 回答
0

另一种选择是将您的工厂方法更改为“配置”方法,并将创建一次性对象的责任交给客户端。例子:

public void SetupDisosableThing(IDisposable foo)
{
 foo.Bar = "baz";
}

void Main()
{
  using (var x = new Thing())
  {
   SetupDisposableThing(x);
  }
}
于 2014-06-06T19:49:44.887 回答