Подтвердить что ты не робот

CA2000 при возврате одноразового объекта из метода

У меня есть метод factory, который строит объекты, которые реализуют IDisposable. В конечном счете это вызывающие, которые управляют временем жизни созданных объектов. Эта конструкция запускает кучу ошибок CA2000. Есть ли что-то принципиально неправильное в моем дизайне, нужно ли ему рефакторинг, или это просто слишком возбуждает предупреждения о статическом анализе кода?

Метод factory

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
}    
4b9b3361

Ответ 1

Я бы рекомендовал вам подавить предупреждение CA2000 для каждого индивидуального метода factory или, возможно, для всего класса, который их содержит (но только если это единственная функция этого класса).

Далее я рекомендую включить обоснование:

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability",
    "CA2000:Dispose objects before losing scope",
    Justification = "This is a factory method. Caller must dispose")]

Ответ 2

Вы должны сохранить его в локальной переменной и перенести инициализацию в блок 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: кто-то ранее упомянул, чтобы убрать внутри окончательно - это, очевидно, неправильно - в пути без исключения вы не хотите вызывать Dispose

Ответ 3

Вы получаете ошибку, потому что создатель одноразового объекта не управляет им. Однако в дизайне нет ничего принципиально неправильного. Вы просто полагаетесь на потребителей, чтобы использовать using. Не так сильно отличается от существующих объектов ADO, например.

Ответ 4

Другой альтернативой является изменение метода factory на метод "конфигурации" и ответственность за создание одноразового объекта на клиенте. Пример:

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

void Main()
{
  using (var x = new Thing())
  {
   SetupDisposableThing(x);
  }
}