2017-01-24 52 views
3

我想写一个处理异常的方法,这将被称为catch块内的方法。根据通过的异常类型,异常无论是作为一个新的异常的内部异常传递或者干脆重新抛出。如何在第二种情况下保留堆栈跟踪?C#重新抛出异常的设计来处理异常和保存堆栈跟踪

例子:

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进行分类外,首选的方法是二catch块:

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

事实上,有使用System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture在.Net4.5这样做的一个非常好的方式:

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

相关问题