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

Исключения .NET и С#. Что разумно ловить

Отказ от ответственности, я из фона Java. Я не делаю много С#. Там существует большая передача между двумя мирами, но, конечно, есть различия, и каждый из них имеет отношение к Исключениям.

Недавно я ответил на вопрос С#, предполагающий, что в некоторых случаях разумно это сделать:

 try {
   some work
 } catch (Exeption e) {
       commonExceptionHandler();
 }

(Причины несущественны). Я получил ответ, который я не совсем понимаю:

до .NET 4.0, очень сложно поймать Исключение. Это означает, что вы поймаете различные низкоуровневые фатальные ошибки и поэтому маскировка ошибок. Это также означает, что в случае какой-то коррупции, которая вызывает такое исключение, любое открытое наконец, блоки в стеке будут выполняется, поэтому даже если Функция callExceptionReporter пытается для входа в систему и выхода, он может даже не получить к этой точке (наконец, блоки могут бросить снова или вызвать больше коррупции, или удалить что-то важное из диска или базы данных).

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

  • Я понимаю, что существует множество исключений низкого уровня, которые мы не хотим глотать. Моя функция commonExceptionHandler() могла бы разумно изменить их. Это похоже на этот ответ на соответствующий вопрос. Что говорит: "В зависимости от вашего контекста может быть приемлемым использование catch (...), при условии, что исключение будет повторно выбрано". Поэтому я заключаю, что использование catch (Exception) не всегда является злым, молчаливо проглатывая некоторые исключения.

  • Фраза "До .NET 4 очень плохо выходить из-за исключения" Какие изменения в .NET 4? Это ссылка на AggregateException, которая может дать нам некоторые новые вещи, связанные с исключениями, которые мы улавливаем, но я не думаю, что меняет основное правило "не усвоить".

  • Следующая фраза действительно беспокоит. Это может быть правильно?

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

Я понимаю, что если какой-то код низкого уровня имел

lowLevelMethod() {
    try {
        lowestLevelMethod();
    } finally {
         some really important stuff
    }
}

и в моем коде я вызываю lowLevel();

 try {
      lowLevel()
 } catch (Exception e) {
       exception handling and maybe rethrowing
 }

Независимо от того, поймал ли я исключение Exception, это не влияет на выделение блока finally. К тому времени, когда мы покинем lowLevelMethod(), наконец-то уже запущен. Если в конечном итоге произойдет какая-либо из плохих вещей, например, поврежденный диск, тогда он это сделает. Мой выбор Исключения не имел никакого значения. Если он достигает моего блока Exception, мне нужно сделать правильные вещи, но я не могу быть причиной dmis-executing finallys

4b9b3361

Ответ 1

Мой девиз - это то, что вы можете (или нужно), и пусть любые другие исключения пузырятся и поймают их в событии UnhandledException.

Вы правы, окончательный блок всегда вызывается (даже в случае возникновения исключения в разделе try) до выхода из метода. Итак, хотите ли вы, чтобы исключить исключение из метода out или нет, полностью зависит от вас..... это не должно влиять на вызываемый блок finally.

Ответ 2

По вопросу № 2: Автор имел в виду "Поврежденные государственные исключения". Они будут представлены в .NET 4.0 (команда CLR объявила об этом на PDC 2008 в в этом разговоре).

Поврежденные исключения состояния не могут быть пойманы обычным блоком catch. Примеры: Нарушение прав доступа, Недопустимая память.

Но вы можете поймать эти исключения:

  • В main() - запись в журнал, выход, выключение addin
  • Очень редкие случаи, когда вы знаете, что код генерирует такое исключение (например, некоторые случаи с interop с собственным кодом)

Чтобы сделать это, вы должны поместить атрибут [HandleProcessCorruptedStateException] в метод, где вы хотите поймать CorruptedStateException.

Чтобы узнать больше об этих исключениях, см. эту статью в MSDN.

Ответ 3

Как правило, вы не должны ловить исключения, если:

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

  • Вы находитесь на верхнем уровне приложения (например, пользовательского интерфейса) и не хотите, чтобы поведение по умолчанию отображалось пользователю. Например, вам может понадобиться диалоговое окно с сообщением стиля "пожалуйста, отправьте нам свои журналы".

  • Вы повторно бросаете исключение, когда-либо обмениваетесь им, например, если вы откатываете транзакцию DB.

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

Если что-то в исключении, которое вам нужно обработать, должно перебросить исключение, например:

try {
    conn.BeginTransaction();
    //do stuff
    conn.CommitTransaction();
}
catch (Exception) {
    conn.RollbackTransaction(); //required action on any exception
    throw; //re-throw, don't wrap a new ex to keep the stack trace
}
finally {
    conn.Dispose(); //always dispose of the resource
}

Ответ 4

Как раз к третьему вопросу:

Если у вас

nastyLowLevel() {
  doSomethingWhichMayCorruptSomethingAndThrowsException();
}

MyEvilCatcher() {
  try {
    nastyLowLevel();
  } catch (Exception e) {
    MyExceptionHandler(e);
  }
}

WiseCatcher() {
  try {
    MyEvilCatcher();
  } catch (LowLevelException e) {
    DoSomethingWiseSoFinnalyDontRuinAnything();
  } finally {
    DoSomethingWhichAssumesLowLevelWentOk();
  }
}

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

В общем, я предпочитаю тщательно обдумывать, какие исключения могут быть брошены и поймать их явно. Я использую "общий обработчик" на самом внешнем уровне в производственных средах, чтобы регистрировать неожиданное исключение и представлять их клиенту в хорошо отформатированном виде (включая подсказку, чтобы отправить нам файл журнала.)

Ответ 5

Я думаю, что цитируемый ответ неправильный (или может означать 2.0 вместо 4.0)? Это звучит для меня немного поддельным.