原本這篇文章就想寫寫StackTrace怎么會丟的問題, 但現在的內容變成了討論怎么處理Exception的問題。
該不該用try catch, 什么時候用?也困擾了我很久, 好像隨便寫寫就可以, 但是事實上還是有Best Practise, 以下內容請您參考,歡迎指正!
StackTrace: 保存方法的棧調用信息。
什么意思呢?A方法里調用了B方法,B方法里調用了C方法,你調用A方法的時候StackTrace里就大概是這樣:
at Project.Class.C in c:\aaa\Project\class.cs:line 10.
at Project.Class.B in c:\aaa\Project\class.cs:line 20.
at Project.Class.A in c:\aaa\Project\class.cs:line 30.
它就是個字符串。
不過他有什么用呢?你說呢,畢竟人家連行號都告訴你了。如果丟了StackTrace,我們也就丟了這些信息。
什么情況下會丟StackTrace?看看這段代碼:
- static void Main(string[] args)
- {
- try
- {
- // Call Method1
- Console.WriteLine(Method1());
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.StackTrace);
- }
- Console.ReadLine();
- }
- public static int Method1()
- {
- try
- {
- return Method1_1();
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
- public static int Method1_1()
- {
- int j = 0;
- return 10 / j;
- }
乍看貌似沒有什么問題,但是Method1多做了一件事: Catch(Exception ex){thorw ex;}
他帶來一個后果就是,StackStace會丟.
得到的StackTrace如下:
at ExceptionMethodCall.Program.Method1() in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 33
at ExceptionMethodCall.Program.Main(String[] args) in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 16
刪除 try..catch, 我們得到的StackTrace如下:
at ExceptionMethodCall.Program.Method1_1() in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 40
at ExceptionMethodCall.Program.Method1() in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 29
at ExceptionMethodCall.Program.Main(String[] args) in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 16
結果顯而易見。
更多:
如果Method1代碼這么寫:
- public static int Method1()
- {
- try
- {
- return Method1_1();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- throw;
- }
- }
會發生什么?
注意:這次沒有throw ex, 而是 throw.
我們發現StackTrace又不會丟了:
at ExceptionMethodCall.Program.Method1_1() in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 40
at ExceptionMethodCall.Program.Method1() in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 29
at ExceptionMethodCall.Program.Main(String[] args) in c:\Projects\ExceptionMethodCall\ExceptionMethodCall\Program.cs:line 16
原因是什么?
我就隨便說說我的想法, 你這么想也行 不這么想也行, 但是我不負責哦:
catch(Exception ex) 會實例化一個Exception 對象,其實就是在此處你catch到的這個Exception。你怎么處理它都可以, 寫log或者Print出來,
但是你就是不要throw 它。 你throw它了,exception stack就被清空。沒有throw 它, exception stack里就始終保存所有exceptions。
在更多:
如果Method1這么寫:
- public static int Method1()
- {
- return Method1_1();
- }
注意:沒有寫任何try.. catch. 可能有人覺得會丟StackTrace, 事實上不會. 這里Method1() call Method1_1(), 它會完整的保存StackTrace。
事實上,你寫更多層都沒有關系, StackTrace依然很完整。
所以綜上所述:
1. 如非必要, 不要給方法加任何try.. catch.., 只在調用方法的最外層處理Exception;
2. 如果需要在方法里處理Exception, 你直接catch(Exception ex)處理就好了, 不要throw ex;