Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
901
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6089
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4401
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Рекомендации по отлову и повторному выбрасыванию исключений .NET
Какие рекомендации следует учитывать при перехвате исключений и повторном их отбрасывании? Я хочу убедиться, что InnerException объекта Exception и стек trace сохранены. Есть ли разница между следующими блоками кода в том, как они обрабатывают это?
try
{
//some code
}
catch (Exception ex)
{
throw ex;
}
Против:
try
{
//some code
}
catch
{
throw;
}
Способ сохранения стека trace заключается в использовании throw; , это также допустимо
try {
// something that bombs here
} catch (Exception ex)
{
throw;
}
throw ex; в принципе похоже на выбрасывание исключения из этой точки, поэтому стек trace будет идти только туда, где вы выдаете оператор throw ex; .
Майк также прав, предполагая, что исключение позволяет вам передать исключение (что рекомендуется).
У Карла Сегина также есть отличная запись об обработке исключений в его электронной книге "Основы программирования ", которая является отличным чтением.
Правка: рабочая ссылка на основы программирования pdf. Просто найдите в тексте "exception".
На самом деле, есть некоторые ситуации, когда заявление throw не сохранит информацию StackTrace. Например, в приведенном ниже коде:
try
{
int i = 0;
int j = 12 / i; // Line 47
int k = j + 1;
}
catch
{
// do something
// ...
throw; // Line 54
}
StackTrace будет означать, что строка 54 вызвала исключение, хотя оно было вызвано в строке 47.
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.
at Program.WithThrowIncomplete() in Program.cs:line 54
at Program.Main(String[] args) in Program.cs:line 106
В ситуациях, подобных описанной выше, есть два варианта предварительной настройки исходного StackTrace:
Вызов Exception.InternalPreserveStackTrace
Поскольку это частный метод, он должен быть вызван с помощью отражения:
private static void PreserveStackTrace(Exception exception)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(exception, null);
}
У меня есть недостаток в том, что я полагаюсь на частный метод сохранения информации StackTrace. Он может быть изменен в будущих версиях фреймворка .NET. Приведенный выше пример кода и предложенное ниже Решение были извлечены из веб- блога Fabrice MARGUERIE .
Вызов Exception.SetObjectData
Техника ниже предложил Антон Тихого , как ответ в C#, как я могу повторно InnerException без потери стека вопрос trace .
static void PreserveStackTrace (Exception e)
{
var ctx = new StreamingContext (StreamingContextStates.CrossAppDomain) ;
var mgr = new ObjectManager (null, ctx) ;
var si = new SerializationInfo (e.GetType (), new FormatterConverter ()) ;
e.GetObjectData (si, ctx) ;
mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData
mgr.DoFixups () ; // ObjectManager calls SetObjectData
// voila, e is unmodified save for _remoteStackTraceString
}
Хотя у него есть преимущество полагаться только на открытые методы, он также зависит от следующего конструктора исключений (который некоторые исключения, разработанные третьими сторонами, не реализуют):
protected Exception(
SerializationInfo info,
StreamingContext context
)
В моей ситуации я должен был выбрать первый подход, потому что исключения, вызванные сторонней библиотекой, которую я использовал, не реализовали этот конструктор.
Эмпирическое правило состоит в том, чтобы не ловить и не бросать основной объект Exception . Это заставляет вас быть немного умнее в отношении исключений; другими словами, вы должны иметь явный catch для SqlException , чтобы ваш код обработки не делал что-то неправильно с NullReferenceException .
В реальном мире, однако, ловить и регистрировать базовое исключение также является хорошей практикой, но не забудьте пройти все это, чтобы получить любой InnerExceptions , который он может иметь.
Никто не объяснил разницу между ExceptionDispatchInfo.Capture( ex ).Throw() и простым throw, так что вот она. Тем не менее, некоторые люди заметили, что проблема с throw .
Полный способ перестроить перехваченное исключение - использовать ExceptionDispatchInfo.Capture( ex ).Throw() (доступно только из .Net 4.5).
Ниже приведены случаи, необходимые для проверки этого:
1.
void CallingMethod()
{
//try
{
throw new Exception( "TEST" );
}
//catch
{
// throw;
}
}
2.
void CallingMethod()
{
try
{
throw new Exception( "TEST" );
}
catch( Exception ex )
{
ExceptionDispatchInfo.Capture( ex ).Throw();
throw; // So the compiler doesn't complain about methods which don't either return or throw.
}
}
3.
void CallingMethod()
{
try
{
throw new Exception( "TEST" );
}
catch
{
throw;
}
}
4.
void CallingMethod()
{
try
{
throw new Exception( "TEST" );
}
catch( Exception ex )
{
throw new Exception( "RETHROW", ex );
}
}
Случай 1 и Случай 2 дадут вам стек trace, где номер строки исходного кода для метода CallingMethod является номером строки throw new Exception( "TEST" ) .
Однако в случае 3 вы получите стек trace, где номер строки исходного кода для метода CallingMethod является номером строки вызова throw . Это означает, что если строка throw new Exception( "TEST" ) окружена другими операциями, вы понятия не имеете, в каком номере строки на самом деле возникло исключение.
Случай 4 аналогичен случаю 2, поскольку номер строки исходного исключения сохраняется, но не является реальным перестроением, поскольку он изменяет тип исходного исключения.
Вы всегда должны использовать "throw;", чтобы перестроить исключения в .NET,
Обратитесь к этому, http://weblogs.asp.net/bhouse/archive/2004/11/30/272297.aspx
В основном MSIL (CIL) имеет две инструкции-"throw" и "rethrow":
- C#'s "throw ex;" компилируется в MSIL "throw"
- C#'s "throw;"-в MSIL "rethrow"!
В принципе, я вижу причину, по которой "throw ex" переопределяет стек trace.
Несколько человек на самом деле упустили очень важный момент - 'throw' и 'throw ex' могут делать то же самое, но они не дают вам решающую часть imformation, которая является линией, где произошло исключение.
Рассмотрим следующий код:
static void Main(string[] args)
{
try
{
TestMe();
}
catch (Exception ex)
{
string ss = ex.ToString();
}
}
static void TestMe()
{
try
{
//here's some code that will generate an exception - line #17
}
catch (Exception ex)
{
//throw new ApplicationException(ex.ToString());
throw ex; // line# 22
}
}
Когда вы делаете либо 'throw', либо 'throw ex', вы получаете стек trace, но line# будет #22, поэтому вы не можете понять, какая именно строка вызвала исключение (если только у вас нет только 1 или нескольких строк кода в блоке try). Чтобы получить ожидаемую строку #17 в вашем исключении, вам придется создать новое исключение с исходным стеком исключений trace.
К вашему сведению, я только что проверил это, и стек trace, о котором сообщает ' throw;', не является полностью правильным стеком trace. Пример:
private void foo()
{
try
{
bar(3);
bar(2);
bar(1);
bar(0);
}
catch(DivideByZeroException)
{
//log message and rethrow...
throw;
}
}
private void bar(int b)
{
int a = 1;
int c = a/b; // Generate divide by zero exception.
}
Стек trace правильно указывает на источник исключения (сообщенный номер строки), но номер строки, сообщенный для foo(), является строкой оператора throw;, следовательно, вы не можете сказать, какой из вызовов bar() вызвал исключение.