2017-01-24 53 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

相關問題