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

Есть ли проблемы с использованием блока для IDisposable внутри блока catch try?


MSDN рекомендует помещать любые экземпляры классов, которые реализуют IDisposable в блок using. Или, альтернативно, если он создается в блоке try-catch, тогда Dispose в Finally.

Существуют ли какие-либо проблемы с использованием блока using в блоке try-catch, например, так?

try
{
    using (Foo bar = new Foo())
    {
       bar.doStuff();
    }
}
catch (Exception e)
{
    //vomit e
}

Конечно, я могу просто вызвать Dispose в блоке Finally, но я новичок в программировании, и мне просто интересно узнать, подходит ли что-то подобное, или если кто-то ударит меня затылок и кричать на меня, что я Doing-It-Wrong™.

Или, скорее, меня больше интересует, почему это было бы неправильно, если бы это было.

4b9b3361

Ответ 1

Нет, это выглядит отлично. Экземпляр вашего бара будет удален до того, как вы попадете в блок catch.

Ответ 2

Это... барабан... абсолютно нормально.

Единственная проблема заключается в том, что вы не должны использовать catch (Exception), но поймать конкретные ошибки, которые вас интересуют (даже если это только пример), но это не влияет на using. Фактически, единственная причина, по которой вы ставите using вне блока try, - это то, что вы хотите продолжить что-то делать с bar, не связанным с кодом, который не удался - в противном случае, чтобы область была как можно меньше как правило, хорошая идея.

Ответ 3

Это нормально, но вы потеряли доступ к объекту, который вызвал бы исключение в исключении.
И ловить общие исключения не считается хорошей практикой

Foo bar = null;
try
{
    bar = new Foo();
    bar.doStuff();
}
catch (IndexOutOfRangeException e)
{
    //vomit e
    Debug.WriteLine(e.msg);
    if(bar == null) 
       Debug.WriteLine("bar = new Foo() failed ");
    else 
       Debug.WriteLine("bar fail ID = " + bar.ID);
}
catch (Exception e)
{
    // ...
    // unless you are going to handle it gracefully you should rethrow it
}
finally 
{
    if(bar != null) bar.Dispose();
}

Ответ 4

Ваш примерный код лишний. Using() документация:

A, используя инструкцию вида

using (ResourceType resource = expression) 
Оператор

соответствует одному из двух возможных расширений. Когда ResourceType - тип значения, расширение

{
   ResourceType resource = expression;
   try {
      statement;
   }
   finally {
      ((IDisposable)resource).Dispose();
   }
}

В противном случае, когда ResourceType является ссылочным типом, расширение

{
   ResourceType resource = expression;
   try {
      statement;
   }
   finally {
      if (resource != null) ((IDisposable)resource).Dispose();
   }
}

В любом расширении переменная ресурса доступна только для чтения во встроенной инструкции.

В конечном итоге ваш код будет выглядеть примерно так:

try
{
    Foo bar = new Foo()
    try
    {
       bar.doStuff();
    }
    finally 
    {
       if (bar != null) ((IDisposable)bar).Dispose();
    }
}
catch (Exception e)
{
    //vomit e
}

Нет реальной причины для двух утверждений try. Это не неправильный код, он просто лишний в контексте нескольких операторов try. Кажется, вы задаете вопрос о Disposing объекта. В этом контексте он избыточен. Если вы также обеспокоены тем, что конструктор объектов выбрасывает исключение, очевидно, что это будет необходимо.

Есть ли проблемы с использованием используемого блока в блоке try-catch, например?

Нет, я пишу ваш пример все время.

Конечно, я могу просто вызвать Dispose в блоке finally,

Сорт, конструктор должен вызываться вне try/catch, иначе переменная будет недоступна к моменту достижения вами блока finally

справедливы:

var foo = new bar();
try
{
}
finally
{
  foo.Dispose();
}

недопустим:

try
{
  var foo = new bar();
}
finally
{
  foo.Dispose();
}

Ответ 5

Нет, это нормально, но если вы хотите получить доступ к bar во время catch, вам понадобится внутренний try catch:

try
{
    using (Foo bar = new Foo())
    {
      try
      {
        bar.doStuff();
      }
      catch (Exception e)
      {
        //vomit e, with bar available.
      }
    }
}
catch (Exception e)
{
    //vomit e, relating to a problem during creation of Foo.
}

или, как было предложено в комментариях, разложить внутренний блок на новый метод.