Разница между броском и броском нового исключения()

какая разница между

try { ... }
catch{ throw } 

и

try{ ... }
catch(Exception e) {throw new Exception(e.message) } 

Независимо от того, что второе показывает сообщение?

Ответ 1

throw; восстанавливает исходное исключение и сохраняет исходную трассировку стека.

throw ex; выдает исходное исключение, но сбрасывает трассировку стека, уничтожая всю информацию о трассировке стека до вашего блока catch.


НИКОГДА писать throw ex;


throw new Exception(ex.Message); еще хуже. Он создает новый экземпляр Exception, теряющий исходную трассировку стека исключения, а также его тип. (например, IOException).
Кроме того, некоторые исключения содержат дополнительную информацию (например, ArgumentException.ParamName).
throw new Exception(ex.Message); также уничтожит эту информацию.

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

Чтобы сделать это, определите новый класс, наследующий Exception, добавить все четыре конструктора исключений, и необязательно дополнительный конструктор, который принимает InnerException, а также дополнительную информацию, и бросает ваш новый класс исключений, передавая ex в качестве параметра InnerException. Передавая исходный InnerException, вы сохраняете все исходные свойства исключения, включая трассировку стека.

Ответ 2

Первый сохраняет исходный стек:

try { ... }
catch
{
    // Do something.
    throw;
}

Второе позволяет вам изменить тип исключения и/или сообщение и другие данные:

try { ... } catch (Exception e)
{
    throw new BarException("Something broke!");
}

Также существует третий способ, по которому вы передаете внутреннее исключение:

try { ... }
catch (FooException e) {
    throw new BarException("foo", e);
} 

Я бы рекомендовал использовать:

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

Ответ 3

throw повторно выбрасывает исключение catch, сохраняя трассировку стека, а throw new Exception теряет некоторые из деталей пойманного исключения.

Обычно вы обычно используете throw для регистрации исключения без полной обработки его в этой точке.

BlackWasp имеет хорошую статью, достаточно озаглавленную Бросать исключения в С#.

Ответ 4

Бросок нового Exception удаляет текущую трассировку стека.

throw; сохранит исходную трассировку стека и почти всегда будет более полезной. Исключением из этого правила является то, что вы хотите обернуть исключение в собственное собственное Исключение. Затем вы должны:

catch(Exception e)
{
    throw new CustomException(customMessage, e);
}

Ответ 5

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

Использование throw без каких-либо аргументов сохраняет стек вызовов для целей отладки.

Ответ 6

Еще один момент, который я не видел никого:

Если вы ничего не делаете в своем блоке catch {}, попытка try... catch бессмысленна. Я все время вижу это:

try 
{
  //Code here
}
catch
{
    throw;
}

Или хуже:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw ex;
}

Хуже всего:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw new System.Exception(ex.Message);
}

Ответ 7

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

Ответ 8

В вашем втором примере будет reset трассировка стека исключений. Первый наиболее точно сохраняет происхождение исключения. Также вы развернули оригинальный тип, который является ключом к пониманию того, что на самом деле пошло не так... Если для функциональности требуется вторая функция - например, Чтобы добавить расширенную информацию или повторно обернуть специальным типом, например пользовательское "HandleableException", просто убедитесь, что свойство InnerException также установлено!

Ответ 9

Самое важное отличие состоит в том, что второе выражение стирает тип исключения. И тип исключения играет жизненно важную роль в исключениях catching:

public void MyMethod ()
{
    // both can throw IOException
    try { foo(); } catch { throw; }
    try { bar(); } catch(E) {throw new Exception(E.message); }
}

(...)

try {
    MyMethod ();
} catch (IOException ex) {
    Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
    Console.WriteLine ("Other error");    // [2]
}

Если foo() throws IOException, блок блокировки [1] поймает исключение. Но когда bar() выбрасывает IOException, он будет преобразован в обычный Exception ant не будет пойман блоком catch [1].

Ответ 10

throw или throw ex, оба используются для броска или повторного исключения исключения, когда вы просто регистрируете информацию об ошибках и не хотите отправлять какую-либо информацию обратно вызывающему, вы просто регистрируете ошибку в catch и leave. Но если вы хотите отправить какую-либо значимую информацию об исключении из вызывающего, который вы используете, бросьте или выбросьте ex. Теперь разница между throw и throw ex заключается в том, что бросок сохраняет трассировку стека и другую информацию, но throw ex создает новый объект исключения и, следовательно, потеряна исходная трассировка стека. Поэтому, когда мы должны использовать throw и throw e, Есть еще несколько ситуаций, в которых вы можете захотеть сбросить исключение, подобное reset информации стека вызовов. Например, если метод находится в библиотеке и вы хотите скрыть детали библиотеки от вызывающего кода, вам не обязательно, чтобы стек вызовов включал информацию о частных методах в библиотеке. В этом случае вы можете перехватывать исключения в общедоступных методах библиотеки, а затем восстанавливать их, чтобы стек вызовов начинался с этих общедоступных методов.