try catch finally簡單的三個(gè)關(guān)鍵字,其處理流程卻較為復(fù)雜,下面先分各種情況討論,最后得出結(jié)論,并提出使用建議。
1 沒有發(fā)生異常的情況
- class Program
- {
- static void Main(string[] args)
- {
- try
- {
-
- Console.WriteLine("in try");
- }
- catch (Exception ex)
- {
- Console.WriteLine("in catch: " + ex.Message);
- }
- finally
- {
- Console.WriteLine("in finally");
- }
- Console.WriteLine("after finally");
- }
輸出為:
in try
in finally
after finally
分析:
由于沒有發(fā)生異常,catch也就捕獲不到,所以不執(zhí)行catch里的代碼,執(zhí)行finally的代碼,然后執(zhí)行后續(xù)代碼。
2.發(fā)生異常,并且被本級catch捕獲
- class Program
- {
- static void Main(string[] args)
- {
- try
- {
- throw new Exception("my exception");
- Console.WriteLine("in try");
- }
- catch (Exception ex)
- {
- Console.WriteLine("in catch: " + ex.Message);
- }
- finally
- {
- Console.WriteLine("in finally");
- }
- Console.WriteLine("after finally");
- }
-
- }
執(zhí)行結(jié)果:
in catch: my exception
in finally
after finally
分析:
try塊發(fā)生異常的語句以后的代碼不再執(zhí)行,而是馬上被catch捕獲,并執(zhí)行catch塊里的代碼,然后執(zhí)行finally塊的代碼,然后執(zhí)行后續(xù)代碼。
3 發(fā)生異常,被上級catch捕獲
代碼:
- class Program
- {
- static void Main(string[] args)
- {
- try
- {
- test();
- Console.WriteLine("in 上一級try");
- }
- catch (Exception ex)
- {
- Console.WriteLine("in 上一級catch: " + ex.Message);
- }
- finally
- {
- Console.WriteLine("in 上一級finally");
- }
- Console.WriteLine("after 上一級的finally");
- }
-
- static void test()
- {
- try
- {
- throw new Exception("my exception");
- Console.WriteLine("in try");
- }
- catch (IOException ex)
- {
- Console.WriteLine("in catch: " + ex.Message);
- }
- finally
- {
- Console.WriteLine("in finally");
- }
- Console.WriteLine("after finally");
- }
- }
執(zhí)行結(jié)果:
in finally
in 上一級catch: my exception
in 上一級finally
after 上一級的finally
分析:
發(fā)生異常后,本級catch沒有捕獲到,異常繼續(xù)向上流轉(zhuǎn),被上一級catch捕獲到后,執(zhí)行本級的finally,然后執(zhí)行上一級的catch,然后執(zhí)行上一級的finally.
本級的finally后面的代碼不會執(zhí)行。
4.發(fā)生異常,沒有被本級catch捕獲,也沒有被上級任何catch捕獲
代碼:
- class Program
- {
- static void Main(string[] args)
- {
- try
- {
- test();
- Console.WriteLine("in 上一級try");
- }
- catch (IOException ex)
- {
- Console.WriteLine("in 上一級catch: " + ex.Message);
- }
- finally
- {
- Console.WriteLine("in 上一級finally");
- }
- Console.WriteLine("after 上一級的finally");
- }
-
- static void test()
- {
- try
- {
- throw new Exception("my exception");
- Console.WriteLine("in try");
- }
- catch (IOException ex)
- {
- Console.WriteLine("in catch: " + ex.Message);
- }
- finally
- {
- Console.WriteLine("in finally");
- }
- Console.WriteLine("after finally");
- }
- }
執(zhí)行結(jié)果:
未經(jīng)處理的異常: System.Exception: my exception
在 ConsoleApplication4.Program.test() 位置 D:\MyProjects\VS2010 Projects\Cons
oleApplication4\ConsoleApplication4\Program.cs:行號 33
在 ConsoleApplication4.Program.Main(String[] args) 位置 D:\MyProjects\VS2010
Projects\ConsoleApplication4\ConsoleApplication4\Program.cs:行號 15
in finally
in 上一級finally
分析:
異常發(fā)生后,本級catch沒有捕獲到,流轉(zhuǎn)到上一級catch,上一級catch也沒有捕獲到,繼續(xù)流轉(zhuǎn)直到CLR,CLR會打印“未處理...",并在用戶按下取消按鈕后,執(zhí)行本級的finally塊,然后執(zhí)行上一級的finally塊,最后強(qiáng)制終止程序。
finally塊后面得內(nèi)容均不能執(zhí)行。
5.結(jié)論
(1)try塊中,沒有發(fā)生異常,try->finally->后續(xù)代碼;
(2)try塊中,發(fā)生異常語句后面的代碼不會執(zhí)行;
(3)try塊中,發(fā)生異常,如果被本級catch捕獲,那么 本級catch塊-->本級finally塊-->后續(xù)代碼;
(4)try塊中,發(fā)生異常,如果被上級catch捕獲,那么 本級finally塊-->上級catch塊-->上級finally塊-->上級后續(xù)代碼;
(5)try塊中,發(fā)生異常,如果沒有被任何級別catch捕獲,那么 本級finally塊-->上級finally塊--->程序終止。
6 異常使用建議(僅供參考)
(1)發(fā)布的程序應(yīng)該盡量避免因?yàn)闆]有catch到異常而被迫關(guān)閉,從而讓用戶覺得你的程序不健壯,所以至少要在最上級catch中捕獲所有異常;
(2)需要清理資源的部分,盡量放入finally塊,因?yàn)闊o論如何finally塊總會被執(zhí)行。