Зачем ловить и отбрасывать исключение в C #?

Я смотрю на статью C # - Data Transfer Object о сериализуемых DTO.

Статья включает в себя этот кусок кода:

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

Остальная часть статьи выглядит вменяемой и разумной (нубу), но этот try-catch-throw вызывает WtfException ... Разве это не эквивалентно тому, чтобы вообще не обрабатывать исключения?

Ergo:

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

Или я упускаю что-то фундаментальное в обработке ошибок в C #? Это почти так же, как Java (за исключением проверенных исключений), не так ли? ... То есть они оба усовершенствовали C ++.

Вопрос переполнения стека Разница между перебросом улова без параметров и бездействием? кажется, поддерживает мое утверждение о том, что try-catch-throw это неоперация.


РЕДАКТИРОВАТЬ:

Просто подвести итог для тех, кто найдет эту тему в будущем ...

НЕ ДЕЛАЙТЕ

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

Информация трассировки стека может иметь решающее значение для определения первопричины проблемы!

ДЕЛАТЬ

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

Поймайте более конкретные исключения, прежде чем менее конкретные (как Java).


Ссылки:

19.05.2009 07:56:55
Хорошее резюме; дополнительные баллы за включение блока finally.
Fredrik Mörk 19.05.2009 19:38:59
Я хотел бы добавить, что вы можете использовать «бросить»; чтобы быть еще более полезным, добавив параметры, которые были отправлены методу в коллекцию e.Data перед "throw;" заявление
Michael Bahig 28.04.2013 15:13:36
@MickTheWarMachineDesigner (и художник, работающий неполный рабочий день). А? Вы говорите об исключениях Microshite Suckwell (вероятно, начиная с 2005 года, насколько я знаю). Я говорил об обработке исключений в целом. И да, я кое-что узнал с тех пор, как опубликовал это НА ЧЕМ НА ЧЕТЫРЕ ГОДА ... Но да, я признаюсь, что у вас есть верное мнение, но я думаю, что вы упустили реальное положение; если ты понимаешь мой дрейф? Этот вопрос касается ОБОБЩЕННОЙ обработки исключений в C #; и более конкретно о отбрасывании исключений ... ВСЕХ видов. Круто?
corlettk 29.04.2013 17:11:40
Пожалуйста, рассмотрите возможность перемещения раздела редактирования сводки в своем вопросе на собственный ответ. Почему, смотрите Редактирование самостоятельного ответа вне вопроса и Ответа, встроенного в вопрос .
DavidRR 26.04.2016 15:28:51
Кто-нибудь не заметил часть «Произошел экскремент»? Похоже, код пошел на какашек!
Jason Loki Smith 31.07.2017 06:15:30
17 ОТВЕТОВ
РЕШЕНИЕ

Первый; способ, которым код в статье делает это, является злом. throw exсбросит стек вызовов в исключении до точки, где находится этот оператор throw; потерять информацию о том, где на самом деле было создано исключение.

Во-вторых, если вы просто поймаете и перебросите таким образом, я не вижу никакой дополнительной ценности, приведенный выше пример кода был бы таким же хорошим (или, учитывая throw exбит, даже лучше) без try-catch.

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

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}
428
19.05.2009 08:06:23
@ Фредрик, просто к вашему сведению (хотя вы, вероятно, знаете), если вы не собираетесь использовать этот exобъект, нет необходимости создавать его экземпляр.
Eoin Campbell 19.05.2009 08:16:37
@Eoin: Если его не создать, было бы довольно сложно его зарегистрировать.
Sam Axe 19.05.2009 08:22:22
Да, я думаю, что "зло" почти правильно ... рассмотрим случай исключения нулевого указателя, генерируемого где-то из большой части кода. Сообщение ванильное, без стекового следа вы остаетесь с "что-то где-то было нулевым". НЕ хорошо, когда производство мертво; и у вас НЕТ минут или меньше, чтобы решить проблему flamin ', и отклонить или исправить ее ... Хорошая обработка исключений стоит на вес золота.
corlettk 19.05.2009 09:14:21
Это правда и для Java ... "throw" против "throw ex"?
JasonStoltz 11.03.2011 15:23:07
@ Джейсон, посмотри на этот вопрос . В Java throw exне перезапускается трассировка стека.
Matthew Flaschen 31.01.2012 18:22:25

Вы не хотите бросать ex - так как это потеряет стек вызовов. См. Обработка исключений (MSDN).

И да, команда try ... catch не делает ничего полезного (кроме потери стека вызовов - так что на самом деле это еще хуже - если только по какой-то причине вы не хотели раскрывать эту информацию).

8
9.04.2015 14:26:09
Вы не теряете весь стек вызовов при использовании throw ex, вы просто теряете часть стека вызовов с той точки, где произошло исключение выше его стека вызовов. Но вы сохраняете стек вызовов из метода, который выбросил исключение, туда, где его вызвал клиент. На самом деле могут быть случаи, когда вы будете использовать это, иначе хорошие люди в Microsoft не допустили бы этого. Тем не менее, я не использовал его. Еще одна проблема, которую следует помнить, это то, что бросать исключения стоит дорого. Делайте это только по очень оправданной причине. Ведение журнала, я думаю, будет оправданным и т. Д.
Charles Owen 20.06.2017 20:42:06

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

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}
11
19.05.2009 08:45:19
Спасибо, да, упаковка исключений (особенно цепочка) совершенно вменяема ... то, что не вменяемое, - это исключение только для того, чтобы вы могли убрать трассировку стека или, что еще хуже, съесть ее.
corlettk 19.05.2009 09:16:45

Не делай этого,

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

Вы потеряете информацию трассировки стека ...

Либо делай,

try { ... }
catch { throw; }

ИЛИ

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

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

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}
117
13.03.2013 14:13:31
Почему бы просто не оставить улов?
AnthonyWJones 19.05.2009 08:07:24
по-прежнему есть смысл оставлять catch {throw; } в нижней части списка конкретных типов исключений catch на том основании, что это доказывает, что автор рассмотрел этот случай, хотя комментария может быть достаточно. Не гадать, когда вы читаете код, это хорошо.
annakata 19.05.2009 08:36:24
Почему-то имя SQLException беспокоит меня.
Michael Myers♦ 20.05.2009 21:13:21
Этот улов (Exception) {throw new Exception (...)} - это то, что вам никогда не следует делать, просто потому, что вы запутываете информацию об исключениях и делаете ненужную фильтрацию исключений в стеке вызовов излишне сложной. Единственный раз, когда вы должны перехватить один тип исключения и выбросить другой, это когда вы реализуете уровень абстракции, и вам необходимо преобразовать тип исключения для конкретного поставщика (например, SqlException вместо XmlException) в более общий (например, DataLoadingException).
jammycakes 18.10.2010 12:14:01
@dark_perfect, вы должны проверить этот аргумент заранее, в начале метода и выбросить ArgumentNullException (быстро потерпеть неудачу).
Andrei Bozantan 19.06.2014 19:45:14

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

Вы можете сказать, Catch io.FileNotFoundExeption exа затем использовать альтернативный путь к файлу или что-то подобное, но все равно выдает ошибку.

Кроме того, выполнение Throwвместо Throw Exпозволяет сохранить полную трассировку стека. Throw ex перезапускает трассировку стека из оператора throw (надеюсь, это имеет смысл).

3
9.04.2015 14:27:36

Разве это не эквивалентно тому, чтобы вообще не обрабатывать исключения?

Не совсем, это не то же самое. Сбрасывает трассировку стека исключения. Хотя я согласен, что это, вероятно, ошибка, и, следовательно, пример плохого кода.

10
19.05.2009 08:11:11

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

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

Чтобы повторить, хотя нет смысла поймать исключение в примере, который вы опубликовали. НЕ делай так!

2
19.05.2009 08:19:11

C # (до C # 6) не поддерживает CIL «отфильтрованные исключения», что делает VB, поэтому в C # 1-5 одной из причин для повторного выброса исключения является то, что у вас недостаточно информации во время catch () чтобы определить, действительно ли вы хотите поймать исключение.

Например, в VB вы можете сделать

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... который не будет обрабатывать MyExceptions с различными значениями ErrorCode. В C # до v6 вам пришлось бы перехватывать и перебрасывать MyException, если ErrorCode не был 123:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

Начиная с C # 6.0 вы можете фильтровать, как с VB:

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}
56
18.12.2016 03:55:17
Дейв, но (по крайней мере, в java) вы бы не генерировали «универсальное» исключение MyException, вы бы определяли СПЕЦИФИЧЕСКИЙ тип исключения и выбрасывали его, позволяя дифференцировать его по типу в блоке catch ... Но да , если вы не являетесь архитектором исключения (я имею в виду SQLException JDBC (опять Java)), который является отвратительно родовым и предоставляет метод getErrorCode () ... Хммм ... У вас есть точка зрения, это просто Я думаю, что есть лучший способ сделать это, где это возможно. Приветствия, приятель. Я очень ценю ваше время. Кит.
corlettk 19.05.2009 09:43:34
Ну, вопрос «Зачем ловить и отбрасывать исключение в C #?», И это ответ. =] ... и даже со специализированными исключениями, фильтры исключений имеют смысл: рассмотрим случай, когда вы, скажем, обрабатываете SqlTimeoutException и SqlConnectionResetException, которые оба являются SqlException. Фильтры исключений позволяют вам перехватывать SqlException только тогда, когда он является одним из этих двух, поэтому вместо того, чтобы загромождать попытку / перехват идентичной обработкой для этих двух, вы можете «перехватить SqlException ex, когда ex это SqlTimeoutException или ex это SqlConnectionResetException». (Я не Дэйв, кстати)
bzlm 19.05.2009 11:48:05
Отфильтрованные исключения идут в C # 6!
Sir Crispalot 7.07.2015 10:09:10

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

3
30.07.2009 15:12:20
Я не понял, о чем вы, пока не прочитал ссылку ... и я все еще не совсем уверен, о чем вы ... я совершенно незнаком с VB.NET. Я думаю, это приводит к тому, что сумма сообщается как «несовместимая», верно? ... Я БОЛЬШОЙ фанат статических методов ... Помимо простоты, вероятность несоответствия меньше, если вы отделите установку атрибутов от кода которая делает реальную работу. Стек "самоочищающийся".
corlettk 4.08.2009 14:31:25
Люди ожидают, что когда они пишут "try {Foo ();} finally {Bar ();}"), между Foo и Bar ничего не происходит. Но это не правда; если ваш вызывающий добавил фильтр исключений, и нет промежуточного 'catch' и бросков Foo (), тогда какой-то другой случайный код вашего вызывающего абонента будет запущен до того, как будет запущен finally (Bar). Это очень плохо, если вы нарушили инварианты или повысили уровень безопасности, ожидая, что они будут «немедленно» восстановлены до нормального значения методом finally, и никакой другой код не увидит временное изменение.
Brian 4.08.2009 17:34:14

Извините, но многие примеры «улучшенного дизайна» до сих пор пахнут ужасно или могут вводить в заблуждение. Попробовав {} catch {log; throw} просто совершенно бессмысленно. Регистрация исключений должна выполняться в центральном месте внутри приложения. в любом случае исключения заполняют трассировку стека, почему бы не записать их где-нибудь вверх и близко к границам системы?

Следует соблюдать осторожность при сериализации вашего контекста (например, DTO в одном из приведенных примеров) только в сообщении журнала. Он может легко содержать конфиденциальную информацию, которая может не попасть в руки всех людей, которые могут получить доступ к файлам журнала. И если вы не добавите новую информацию в исключение, я действительно не вижу смысла в исключении. У старой доброй Java есть кое-что для этого, она требует, чтобы вызывающая сторона знала, какие исключения следует ожидать, затем вызывая код. Поскольку в .NET этого нет, обертывание не приносит пользы, по крайней мере, в 80% случаев, которые я видел.

1
16.09.2009 07:22:00
Спасибо за твою мысль, Джо. В Java (и C #, я полагаю) я хотел бы видеть аннотацию на уровне класса @FaultBoundary, которая заставляет ВСЕ исключения (включая непроверенные типы исключений) быть пойманными или объявленными для выброса. Я бы использовал эту аннотацию на открытых интерфейсах каждого архитектурного слоя. Таким образом, интерфейс @FaultBoundary ThingDAO не сможет пропускать детали реализации, такие как SQLExceptions, NPE или AIOB. Вместо этого будет записана «причинная» трассировка стека и будет сгенерировано исключение DAOSystemException ... Я определяю системное исключение как «постоянно фатальное».
corlettk 3.12.2009 10:49:12
Есть много причин, чтобы поймать, войти, а затем сбросить. В частности, если метод с журналом перехвата содержит информацию, которую вы теряете, когда выходите из метода. Ошибка может быть обработана позже, но не записана, и вы потеряли информацию о дефектах в системе.
Andy 9.04.2012 17:50:37
Именно здесь удобно использовать свойство Data класса Exception - захват всей этой локальной информации для общей регистрации. Первоначально эта статья привлекла мое внимание: blog.abodit.com/2010/03/…
McGuireV10 17.12.2014 17:53:58

Моя главная причина для того, чтобы иметь такой код:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

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

Они хороши во время отладки.

14
9.04.2015 14:28:42
Да, я заплачу это, но да, вы не хотели бы видеть это в опубликованном коде ... ergo: мне было бы стыдно опубликовать это ;-)
corlettk 19.09.2009 06:36:23
На самом деле, в этом нет необходимости - в Visual Studio вы можете настроить прерывание отладчика при возникновении исключения, и оно отобразит детали исключения в окне инспектора.
jammycakes 15.10.2009 15:26:05
Если вы хотите использовать какой-то код ТОЛЬКО во время отладки, используйте #if DEBUG ... #endif, и вам не нужно удалять эти строки
Michael Freidgeim 25.12.2012 22:22:31
Я сделал это несколько раз сам. Время от времени каждый сбежит к выпуску. @jammycakes Проблема с разрывом исключений в Visual Studio заключается в том, что иногда я хочу, чтобы выбрасываемое исключение было не единственным (или даже только одним из его типов). Все еще не знаю условия точки останова с «break, если пропущено исключение». До тех пор это останется полезным. Майкл Фрайдгейм: #if DEBUGвокруг ОБА try {и } catch () {...}немного грязно и, честно говоря, меня тошнит ... Препроцессор, вообще говоря, не мой друг.
user645280 11.07.2014 14:23:41

В дополнение к тому, что сказали другие, см. Мой ответ на связанный вопрос, который показывает, что перехват и перебрасывание не запрещены (это в VB, но часть кода может быть вызвана из C # из VB).

1
23.05.2017 12:26:38
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. - Из обзора
LHIOUI 12.10.2018 21:48:52
@HamzaLH, я согласен, что это не очень хорошо написанный ответ, но в нем есть информация, отличная от других ответов и положительных голосов. Поэтому я не понимаю, почему вы предлагаете удалить его? «Короткие ответы по теме, которые дают решение, остаются ответами». От meta.stackexchange.com/questions/226258/…
Michael Freidgeim 13.10.2018 12:43:18
это только для ссылки ответ
LHIOUI 13.10.2018 12:48:30
1. Ответы, содержащие только ссылки, должны быть изменены на комментарии, а не удалены. 2. Это ссылка на другой вопрос SO, а не на внешний сайт, который считается менее вероятным с течением времени. 3. У него есть дополнительное описание, которое делает его не «только ссылкой» - см. Meta.stackexchange.com/questions/225370/…
Michael Freidgeim 14.10.2018 21:25:52

Большинство ответов говорят о сценарии catch-log-rethrow.

Вместо того, чтобы писать это в вашем коде, рассмотрите возможность использования AOP, в частности Postsharp.Diagnostic.Toolkit с OnExceptionOptions IncludeParameterValue и IncludeThisArgument

1
25.12.2012 22:41:10
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. - Из обзора
Tony Dong 12.10.2018 22:41:26
@ ТониДонг, я согласен, что это не очень хорошо написанный ответ, но в нем есть информация, отличная от других ответов и положительных голосов. Поэтому я не понимаю, почему вы предлагаете удалить его? Кстати, ссылка через 5 лет остается в силе. «Короткие ответы по теме, которые дают решение, остаются ответами». От meta.stackexchange.com/questions/226258/…
Michael Freidgeim 13.10.2018 12:41:44
Stackoverflow имеет только это предложение.
Tony Dong 15.10.2018 21:38:42
@TonyDong, если ответ не является абсолютно бесполезным, вы должны выбрать «выглядит хорошо»
Michael Freidgeim 28.10.2018 11:59:14

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

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

В большинстве языков .NET единственный способ для кода выполнить действие, основанное на исключении, - catchэто выполнить его (даже если он знает, что не собирается разрешать исключение), выполнить соответствующее действие и затем выполнить его повторно throw). Другой возможный подход, если коду не важно, какое исключение выдается, это использовать okфлаг с try/finallyблоком; установите okфлаг falseперед блоком и trueперед выходом блока и перед любым блоком, returnкоторый находится внутри блока. Затем, внутри finally, предположим, что если okне установлено, должно произойти исключение. Такой подход семантически лучше, чем catch/ throw, но уродлив и менее ремонтопригоден, чем должен быть.

5
14.11.2014 20:16:51

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

Примером этого является то, что у вас есть метод, в котором вы устанавливаете курсор (например, курсор ожидания), метод имеет несколько точек выхода (например, if () return;), и вы хотите убедиться, что курсор сброшен при конец метода.

Для этого вы можете обернуть весь код в try / catch / finally. В конце установите курсор обратно на правый курсор. Чтобы вы не хоронили никаких действительных исключений, сбросьте их в улов.

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}
3
9.08.2016 11:47:08
Была catchли обязательная часть try...finallyисторически или она играет функциональную роль в этом примере? - Я просто дважды проверил, и я могу использовать try {} finally {}вообще без блока catch.
Sebi 18.12.2018 14:53:04

Это может быть полезно, когда ваши функции программирования для библиотеки или DLL.

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

Я думаю, что это просто используется, чтобы выброшенные исключения были чище и не уходили в «корни» библиотеки.

5
27.05.2018 15:35:30

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

Пример:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Однако есть и другой способ сделать это, используя условные предложения в блоках catch:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

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

0
9.12.2019 17:08:38