Ловля исключений. Вы заменяете или переносите оператор использования? - PullRequest
0 голосов
/ 18 ноября 2011

Оператор using не захватывает исключения. Чтобы поймать исключения, у вас есть два варианта:

1) Разверните и используйте его вручную:

void MyFunc()
{
    StreamReader myReader = null;

    try
    {
        myReader = new StreamReader(path);
        //use myReader
    }
    catch (Exception e)
    {
        //do something with exception
    }
    finally
    {
        if (myReader != null)
            myReader.Dispose();
    }
}

или 2) сохраните использование и оберните его в другой блок try catch

void MyFunc()
{
    try
    {
        using (StreamReader myReader = new StreamReader(path))
        {
             //use myReader
        }
    }
    catch (Exception e)
    {
        //do something with exception
    }
}

Для меня второй выглядит аккуратнее, особенно если вы используете несколько операторов using, потому что он лучше описывает поток и удаляет явные объявления, проверки на нуль и вызовы Dispose ().

Однако, он чувствует себя неправильно из-за дополнительной попытки перехвата, которая эффективно избыточна.

Какая стандартная практика?

Ответы [ 3 ]

6 голосов
/ 18 ноября 2011

Служебные конструкции обработки исключений - это просто метаданные. Производительность не снижается, если не генерируется исключение. В отличие от некоторых других сред выполнения, вход / выход из условия обработки исключений бесплатен в .net. Когда генерируется исключение, среда выполнения использует метаданные и текущий указатель инструкции, чтобы выяснить, какие пункты обработки следует выполнить.

Я предпочитаю второй. Освобождение ресурсов и обработка исключений являются отдельными понятиями, поэтому вполне естественно, что они разделены в коде.

0 голосов
/ 21 ноября 2011

Еще один шаблон, о котором следует помнить - особенно полезен в тех случаях, когда создаваемый объект становится владельцем другого объекта (я обычно пишу код vb.net, поэтому извиняюсь за любые ошибки C #)

class MyDisposableClass
{
  SomeDisposableThing myThing;

  MyDisposableClass() // Constructor
  {
    bool ok = false;

    try
    {
      myThing = new SomeDisposableThing();
      ... do some other stuff
      ok = true;
    }
    finally
    {
      if (!ok)
      {
        zap(ref myThing);
      }
    }
  }
  static void zap<T>(ref T thing) where T:IDisposable,class
  {
    T oldValue = System.Threading.Interlocked.Exchange(thing, null);
    if (oldValue != null)
      oldValue.Dispose();
  }
}

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

0 голосов
/ 18 ноября 2011

Вы должны стараться избегать "try - catch" в методах, до тех пор, пока для этого нет особых требований.Как, например, проверка подключения к базе данных перед запуском приложения.

Обработка исключений становится очень дорогостоящим делом в приложении .Net.

Тем не менее, если вам нужно, то отображаемый второй вариант лучше,Опять же, это субъективно, к самому требованию обработки исключений.

Если это для общей обработки ошибок (таких как регистрация или отправка сообщений об ошибках), тогда используйте Global.asax.Или, по крайней мере, ограничьте его событием Page_Error.

...