2017-01-24 4 views
3

Я хочу написать метод, который обрабатывает исключения и который будет вызываться внутри блока catch. В зависимости от типа переданного исключения исключение либо передается как внутреннее исключение нового исключения, либо просто повторно забрасывается. Как сохранить трассировку стека во втором случае?C# re-throw exception в методе, предназначенном для обработки исключений и сохраняющем stacktrace

Пример:

public void TestMethod() 
{ 
    try 
    { 
     // can throw an exception specific to the project or a .Net exception 
     SomeWorkMethod() 
    } 
    catch(Exception ex) 
    { 
     HandleException(ex); 
    } 
} 

private void HandleException(Exception ex) 
{ 
    if(ex is SpecificException) 
     throw ex; //will not preserve stack trace... 
    else 
     throw new SpecificException(ex); 
} 

То, что я не хотел бы делать это, потому что картина повторяется во многих местах, и там не будет факторизация:

try 
{ 
    SomeWorkMethod(); 
} 
catch(Exception ex) 
{ 
    if(ex is SpecificException) 
     throw; 
    else 
     throw new SpecificException(ex); 
} 
+3

Почему вы не использовать что-то вроде "если бросить (HandleException (ех)!);". Я знаю, что это не совсем то, что вы хотите, но это просто и не очень похоже на второй пример. – Julo

+2

Почему у вас нет отдельного улова для 'SpecificException'? 'catch (SpecificException e) {throw;}' – juharr

ответ

6

Вы должны использовать throw без указав исключение для сохранения трассировки стека. Это можно сделать только внутри блока catch. Что вы можете сделать, это вернуться из HandleException без метания оригинального исключения, а затем использовать throw сразу после этого:

public void TestMethod() 
{ 
    try 
    { 
     // can throw an exception specific to the project or a .Net exception 
     SomeWorkMethod() 
    } 
    catch(Exception ex) 
    { 
     HandleException(ex); 
     throw; 
    } 
} 

private void HandleException(Exception ex) 
{ 
    if(ex is SpecificException) 
     return; 
    else 
     throw new SpecificException(ex); 
} 

Пока вы используете только is классифицировать исключение, предпочтительный способ состоит из двух уловах блоков:

public void TestMethod() 
{ 
    try 
    { 
     // can throw an exception specific to the project or a .Net exception 
     SomeWorkMethod() 
    } 
    catch (SpecificException) 
    { 
     throw; 
    } 
    catch(Exception ex) 
    { 
     throw new SpecificException(ex); 
    } 
} 

с C# 6.0 вы можете также использовать when проронить исключение через:

public void TestMethod() 
{ 
    try 
    { 
     // can throw an exception specific to the project or a .Net exception 
     SomeWorkMethod() 
    } 
    catch(Exception ex) when (!(ex is SpecificException)) 
    { 
     throw new SpecificException(ex); 
    } 
} 
-2

Возможно, вы можете попробовать это.

if(ex.Gettype() == typeof(SpecificException)) 
+0

На самом деле это не затрагивает вопрос, насколько я могу судить. Или, по крайней мере, если это возможно, это может сделать некоторые дополнительные объяснения, чтобы сказать, как это сделать. – Chris

+0

Это неправильно во многих аспектах. Зачем использовать рефлексию? Что, если 'ex' наследует от' SpecificException'? Почему бы не использовать обычные языковые конструкции, такие как 'is' (который OP уже делает)? – Sefe

3

На самом деле, есть очень хороший способ сделать это в .Net4.5 с помощью System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture:

void Main() 
{ 
    try 
    { 
     throw new Exception(); //appears to be thrown from here 
    } 
    catch(Exception ex) 
    { 
     ThrowEx(ex); 
    } 

} 
public void ThrowEx(Exception ex) 
{ 
    if(someCondition) 
    { 
     //we're in the scope of a `catch` and the exception 
     //is "active", so the exception with original stack-trace 
     //can be re-thrown with 
     ExceptionDispatchInfo.Capture(ex).Throw(); 
     //the following line is unreachable, but the compiler doesn't realise 
     //so we can "tell" the compiler that this branch ends in an exception 
     //and avoid having to return anything in the non-void case 
     throw new Exception(); 
    } 
} 
+0

Спасибо, сеньор, вы очень точно отвечаете на мой вопрос. Однако я не заметил, что есть способы добиться того, что мне нужно, используя множество блоков catch (второй ответ от Sefe). –

+0

@SylvainB. В самом деле. Принятый ответ определенно более подходит для ваших нужд. Ваш вопрос напомнил мне, что я видел это некоторое время назад, так что, похоже, стоит поделиться. – spender

 Смежные вопросы

  • Нет связанных вопросов^_^