throw和throw ex的區別


 

之前,在使用異常捕獲語句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的樂趣吧...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM