void show(string tag) { Console.WriteLine(tag); } void methodA() { throw new Exception("error msg"); show("A"); } void methodB() { methodA(); show("B"); } void methodC() { try { methodB(); show("C"); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
這裡為了方便我們理解將程式展開成下面的樣子:
void show(string tag) { Console.WriteLine(tag); } void methodC() { try { methodB(); void methodB() { methodA(); void methodA() { throw new Exception("error msg"); //----------------------------------------------------- show("A"); } show("B"); } show("C"); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
從範例中我們可以看出兩個特性:
* 通透性
從 throw 的那一行開始 Exception 會一直向上傳遞,直到 catch 的區段。
* 脫離性
從 throw 的那一行之後的程式都不會被執行,會有類似 return 的效果,不同的是會對每一層的 method 都進行脫離,包含 try 的區段也會脫離。
methodC 的 catch 會捕獲從 methodA 丟出的 Exception,並且 Exception 中的 StackTrace 會紀錄 methodA, methodB, methodC,而 show() 都不會被執行。
由於大部分的程式邏輯都可以轉化成 else 就離開的程式流程,正好符合 throw 的脫離性,所以我們一開始在撰寫程式邏輯的時候,可以先專注在一般正常的流程邏輯上,之後再去補足檢查邏輯或脫離邏輯,最後在合適的位置進行 try catch 處理,或者在全域的錯誤處理中進行處理。
這裡有一個糟糕的 method,他用了個 Result 物件來裝載回傳結果以及錯誤訊息:
public class Result { public int Value { get; set; } public string Error { get; set; } } public Result BadMethod(int input) { var result = new Result(); if (input > 0) { result.Value = 100 / input; } else { result.Error = "input 需要大於零"; } return result; }
如果用 Exception 可以讓程式簡單很多:
public int GoodMethod(int input) { if (input <= 0) { throw new Exception("input 需要大於零"); } return 100 / input; }
沒有留言:
張貼留言
你好!歡迎你在我的 Blog 上留下你寶貴的意見。