Есть несколько постов, которые спрашивают, какая разница между этими двумя уже есть.
(почему я должен даже упомянуть об этом ...)
Но мой вопрос отличается от того, что я называю «throw ex» в другом богоподобном методе обработки ошибок.
public class Program {
public static void Main(string[] args) {
try {
// something
} catch (Exception ex) {
HandleException(ex);
}
}
private static void HandleException(Exception ex) {
if (ex is ThreadAbortException) {
// ignore then,
return;
}
if (ex is ArgumentOutOfRangeException) {
// Log then,
throw ex;
}
if (ex is InvalidOperationException) {
// Show message then,
throw ex;
}
// and so on.
}
}
Если бы try & catch
были использованы в Main
, то я бы использовал, throw;
чтобы сбросить ошибку. Но в приведенном выше упрощенном коде все исключения проходятHandleException
Имеет ли throw ex;
тот же эффект, что и вызов, throw
когда вызывается изнутри HandleException
?
c#
.net
exception
exception-handling
dance2die
источник
источник
Ответы:
Да, есть разница;
throw ex
сбрасывает трассировку стека (так что ваши ошибки могут появитьсяHandleException
)throw
нет - первоначальный преступник будет сохранен.источник
(Я отправил ранее, и @Marc Gravell исправил меня)
Вот демонстрация разницы:
и вот вывод:
Вы можете видеть, что в Исключении 1 трассировка стека возвращается к
DivByZero()
методу, тогда как в Исключении 2 это не так.Обратите внимание, однако, что номер строки, показанный в
ThrowException1()
иThrowException2()
является номером строкиthrow
оператора, а не номером строки вызоваDivByZero()
, что, вероятно, имеет смысл сейчас, когда я немного об этом подумаю ...Выход в режиме выпуска
Исключение 1:
Исключение 2:
Поддерживает ли исходный stackTrace только в режиме отладки?
источник
DevideByZero
, поэтому трассировка стека одинакова. может быть, вы должны опубликовать это как вопрос сам по себеДругие ответы совершенно верны, но я думаю, что этот ответ дает некоторые дополнительные детали.
Рассмотрим этот пример:
Если вы раскомментируете
throw arithExc;
строку, вы получите:Конечно, вы потеряли информацию о том, где произошло это исключение. Если вместо этого вы используете
throw;
строку, это то, что вы получите:Это намного лучше, потому что теперь вы видите, что именно этот
Program.Div
метод вызывал у вас проблемы. Но все еще трудно понять, возникает ли эта проблема из строки 35 или строки 37 вtry
блоке.Если вы используете третий вариант, заключая внешнее исключение, вы не потеряете информацию:
В частности, вы можете видеть, что это строка 35, которая приводит к проблеме. Тем не менее, это требует от людей поиска
InnerException
, и в некоторых случаях кажется довольно косвенным использовать внутренние исключения.В этом блоге они сохраняют номер строки (строки блока TRY) по телефону (посредством отражения) по
internal
методе входа в инстансеInternalPreserveStackTrace()
наException
объекте. Но не очень хорошо использовать такое отражение (.NET Framework может изменить своихinternal
членов однажды без предупреждения).источник
давайте поймем разницу между броском и броском экс. Я слышал, что во многих интервью .net спрашивают этот общий вопрос.
Просто чтобы дать обзор этих двух терминов, оба броска и броска ex используются, чтобы понять, где произошло исключение. Throw ex перезаписывает трассировку стека исключения независимо от того, где фактически был брошен.
Давайте разберемся с примером.
Давайте разберемся первым броском.
выход вышеизложенного ниже.
показывает полную иерархию и имя метода, где на самом деле сгенерировано исключение .. это M2 -> M2. вместе с номерами строк
Во-вторых .. давайте разберемся, бросив экс. Просто замените throw на throw ex в блоке catch метода M2. как ниже.
вывод команды throw ex code показан ниже.
Вы можете увидеть разницу в выходных данных. Throw ex просто игнорирует всю предыдущую иерархию и сбрасывает трассировку стека с помощью строки / метода, в которую записывается throw ex.
источник
Когда вы это делаете
throw ex
, то выброшенное исключение становится «оригинальным». Таким образом, все предыдущие трассировки стека не будут там.Если вы это сделаете
throw
, исключение просто пойдет по линии, и вы получите полную трассировку стека.источник
Нет, это приведет к тому, что у исключения будет другая трассировка стека. Только используя
throw
без исключения объект вcatch
обработчике оставит трассировку стека без изменений.Вы можете захотеть вернуть логическое значение из HandleException, независимо от того, будет ли исключение переброшено или нет.
источник
MSDN означает :
источник
Посмотрите здесь: http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html
Бросить :
Это сохраняет информацию стека с исключением
Это называется "Ретроу"
Если хотите бросить новое исключение,
Брось Ex :
Это не отправит информацию о стеке с исключением
Это называется «Разбить стек»
Если хотите бросить новое исключение,
источник
Чтобы дать вам другое представление об этом, использование throw особенно полезно, если вы предоставляете клиенту API и хотите предоставить подробную информацию трассировки стека для своей внутренней библиотеки. Используя здесь throw, я бы получил трассировку стека в этом случае библиотеки System.IO.File для File.Delete. Если я использую throw ex, то эта информация не будет передана моему обработчику.
источник
если все строки 1, 2 и 3 прокомментированы - Выход - внутренний экс
если все строки 2 и 3 закомментированы - Выходные данные - внутренняя от System.DevideByZeroException: {"Попытка деления на ноль."} ---------
если все строки 1 и 2 прокомментированы - Выход - внутренний ex System.Exception: делится на 0 ----
если все строки 1 и 3 закомментированы - Выход - внутренний ex System.DevideByZeroException: {"Попытка деления на ноль."} ---------
и StackTrace будет сброшен в случае броска ex;
источник