Изобилие блоков?

Я хотел бы получить ваше мнение по следующему вопросу:

Представьте, что у нас есть метод, который отвечает за достижение одной конкретной цели, но для этого ему нужна поддержка значительного числа объектов с локальной областью видимости, многие из которых реализуют IDisposable .

Стандарты кодирования MS говорят, что при использовании локальных IDisposable объектов, которые не должны «выжить» в области видимости метод (не будет возвращен или не будет назначен для информации о состоянии некоторого более долгоживущего объекта , например), вам следует использовать конструкцию using .

Проблема в том,что в некоторых ситуациях вы можете получить вложенный «ад» , используя блоки:

using (var disposableA = new DisposableObjectA())
{
     using (var disposableB = new DisposableObjectB())
     {
          using (var disposableC = new DisposableObjectC())
          {
               //And so on, you get the idea.
          }
     }
}

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

using (var disposableA = new DisposableObjectA())
{
     using (DisposableBaseObject disposableB = new DisposableObjectB(),
            disposableC = new DisposableObjectC)
     {
          using (var disposableD = new DisposableObjectD())
          {
               //And so on, you get the idea.
          }
     }
}

Другой вариант - не использовать с использованием блоков и реализовать напрямую try-catch блоки. Это будет выглядеть так:

DisposableObjectA disposableA = null;
DisposableObjectB disposableB = null;
DisposableObjectC disposableC = null;
...

try
{
    disposableA = new DisposableObjectA();
    ....
}
finally
{
     if (disposableA != null)
     {
          disposableA.Dispose();
     }

     if (disposableB != null)
     {
          disposableB.Dispose();
     }

     //and so on
}

Забавно, что VS Code Analyzer помечает этот код как «неправильный». Он сообщит вам, что не все возможные пути выполнения гарантируют, что все одноразовые объекты будут удалены перед выходом за пределы области действия. Я могу видеть это только в том случае, если какой-то объект бросает при утилизации, что, по моему мнению, никогда не должно происходить, и если это произойдет, это обычно признак того, что что-то действительно не так, и вам, вероятно, лучше выйти так же быстро и изящно, как вы можно из всего вашего приложения.

Итак, вопрос в том, какой подход вам больше нравится? Всегда ли предпочтительнее использовать вложенные с использованием блоков, независимо от их количества, или, после определенного предела, лучше использовать блок try-catch ?

8
задан InBetween 3 June 2011 в 12:48
поделиться