之前,在使用異常捕獲語句try...catch...throw語句時,一直沒太留意幾種用法的區別,前幾天調試程序時無意中了解到幾種使用方法是有區別的,網上一查,還真是,主要是區別在堆棧信息的起始點不同。總結如下:
我們都知道,C#中使用throw和throw ex拋出異常,但二者是有區別的。
在C#中推薦使用throw;來拋出異常;throw ex;會將到現在為止的所有信息清空,認為你catch到的異常已經被處理了,只不過處理過程中又拋出新的異常,從而找不到真正的錯誤源。
throw的用法主要有以下幾種:
第一種(不推薦使用,可惜很多人都一直這么用的,包括俺,嘻嘻),這樣適用會吃掉原始異常點,重置堆棧中的異常起始點:
View Code
try { } catch (Exception ex) { throw ex; }
第二種,可追溯到原始異常點,不過編譯器會警告,定義的ex未有使用:
View Code
try { } catch (Exception ex) { throw; }
第三種,不帶異常參數的,這個同第二種其實一樣,可捕獲所有類型的異常,IDE不會告警:
View Code
try { } catch { throw; }
其實第二種和第三種用法,書上也是不建議使用的,一般要從小粒度的異常捕獲開始,采用多個catch語句,大家就見仁見智吧。。。
第四種:經過對異常重新包裝,但是會保留原始異常點信息。推薦使用。
View Code
try { } catch (Exception ex) { throw new Exception("經過進一步包裝的異常", ex); }
下面用個例子來加以說明:
View Code
1 /// <summary> 2 /// 入口方法 3 /// </summary> 4 public static void Main() 5 { 6 ExceptionClass ec = new ExceptionClass(); 7 8 try 9 { 10 ec.ExceptionThrow1(); 11 } 12 catch (Exception ex) 13 { 14 Console.WriteLine(ex.ToString()); 15 } 16 17 Console.WriteLine("---------------------------------------------------------------------"); 18 19 try 20 { 21 ec.ExceptionThrow2(); 22 } 23 catch (Exception ex) 24 { 25 Console.WriteLine(ex.ToString()); 26 } 27 28 Console.WriteLine("---------------------------------------------------------------------"); 29 30 try 31 { 32 ec.ExceptionThrow3(); 33 } 34 catch (Exception ex) 35 { 36 Console.WriteLine(ex.ToString()); 37 } 38 39 Console.WriteLine("---------------------------------------------------------------------"); 40 41 try 42 { 43 ec.ExceptionThrow4(); 44 } 45 catch (Exception ex) 46 { 47 Console.WriteLine(ex.ToString()); 48 } 49 50 Console.WriteLine("---------------------------------------------------------------------"); 51 52 Console.ReadKey(); 53 } 54 } 55 56 /// <summary> 57 /// 該Class用來測試異常拋出時相關上下文棧的調用情況 58 /// </summary> 59 public class ExceptionClass 60 { 61 /// <summary> 62 /// 拋出異常方法 63 /// </summary> 64 public void ExceptionThrow1() 65 { 66 try 67 { 68 // 調用原始異常拋出方法來拋出異常 69 this.ExceptionMethod(); 70 } 71 catch (Exception ex) 72 { 73 throw ex; 74 } 75 } 76 77 /// <summary> 78 /// 拋出異常方法1 79 /// </summary> 80 public void ExceptionThrow2() 81 { 82 try 83 { 84 this.ExceptionMethod(); 85 } 86 catch (Exception ex) 87 { 88 throw; 89 } 90 } 91 92 /// <summary> 93 /// 拋出異常方法2 94 /// </summary> 95 public void ExceptionThrow3() 96 { 97 try 98 { 99 this.ExceptionMethod(); 100 } 101 catch 102 { 103 throw; 104 } 105 } 106 107 /// <summary> 108 /// 拋出異常方法3 109 /// </summary> 110 public void ExceptionThrow4() 111 { 112 try 113 { 114 this.ExceptionMethod(); 115 } 116 catch (Exception ex) 117 { 118 throw new Exception("經過進一步包裝的異常", ex); 119 } 120 } 121 122 /// <summary> 123 /// 原始異常拋出方法 124 /// </summary> 125 private void ExceptionMethod() 126 { 127 throw new DivideByZeroException(); 128 } 129 }
運行結果如下:

從運行的結果可以看到,第一種用法已經吃掉了原始異常信息。而其它3種用法都可以追溯到原始異常,推薦使用第四種用法,希望大家能了解這些細微的差別,享受Coding的樂趣吧...

浙公網安備 33010602011771號