C#中的異常處理問題try catch finally
C#中的異常處理是一種檢測(cè)和處理代碼中運(yùn)行時(shí)錯(cuò)誤的機(jī)制,由try catch和finaly塊提供支持。
.NET框架提供了常見異常的內(nèi)置類。
程序執(zhí)行期間發(fā)生的異常,它們可能是由于邏輯或系統(tǒng)錯(cuò)誤引起的。
如果程序員未提供處理這些異常的機(jī)制,則.NET運(yùn)行時(shí)環(huán)境將提供默認(rèn)機(jī)制,該機(jī)制將終止程序執(zhí)行。
try..catch..finally
C#提供了三個(gè)關(guān)鍵字try,catch和finally,以實(shí)現(xiàn)異常處理。
嘗試將可能引發(fā)異常的語句括起來,而如果存在則catch會(huì)處理異常。
finally 可以用于完成任何需要清理的工作。
try..catch..finally塊示例:
try { //可能導(dǎo)致異常的語句 } catch(Type x) { //處理異常的語句 } finally { //任何清理代碼 }
如果try塊內(nèi)部發(fā)生任何異常,則控制權(quán)轉(zhuǎn)移到適當(dāng)?shù)腸atch塊,然后轉(zhuǎn)移到finally塊。
但是在C#中,catch和finally塊都是可選的。
try塊可以與一個(gè)或多個(gè)catch塊或finally塊一起存在,也可以與catch和finally塊一起存在。
如果try塊內(nèi)沒有發(fā)生異常,則控件直接轉(zhuǎn)移到finally塊??梢哉f,finally塊中的語句總是執(zhí)行的。
請(qǐng)注意,通過使用break,continue,return或goto將控制權(quán)從finally塊中移出是錯(cuò)誤的。
在C#中,異常不過是Exception類型的對(duì)象。Exception 是C#中任何異常的最終基類。
C#本身提供了幾個(gè)標(biāo)準(zhǔn)異常。甚至用戶也可以創(chuàng)建自己的異常類,前提是該異常類應(yīng)繼承自Exception類或Exception類的標(biāo)準(zhǔn)派生類之一,例如DivideByZeroExcpetion到ArgumentException等。
未捕獲的異常
以下程序可以通過編譯,但在執(zhí)行過程中將出現(xiàn)錯(cuò)誤。
一個(gè)數(shù)除零是運(yùn)行時(shí)異常,程序終止并顯示錯(cuò)誤消息。
當(dāng)前上下文中任何未捕獲的異常都會(huì)傳播到更高的上下文,并尋找適當(dāng)?shù)腸atch塊來處理它。
如果找不到任何合適的catch塊,.NET運(yùn)行時(shí)的默認(rèn)機(jī)制將終止整個(gè)程序的執(zhí)行。
using System; class MyException { public static void Main() { int x = 0; int div = 100/x; Console.WriteLine(div); } }
具有異常處理機(jī)制的上述程序的修改形式如下:
在這里,我們使用標(biāo)準(zhǔn)異常類DivideByZeroException的對(duì)象來處理由除零引起的異常。
using System; class MyException { public static void Main() { int x = 0; int div = 0; try { div = 100 / x; Console.WriteLine("此行未執(zhí)行"); } catch (DivideByZeroException) { Console.WriteLine("發(fā)生異常"); } Console.WriteLine($"結(jié)果為 {div}"); } }
以上代碼的結(jié)果如下所示:
在上述情況下,程序不會(huì)意外終止。
程序控制從try塊內(nèi)發(fā)生異常的地方轉(zhuǎn)移到catch塊,如果找到任何合適的catch塊,則在該catch中執(zhí)行語句,然后繼續(xù)正常執(zhí)行程序語句。
如果存在以下代碼的finally塊,則finally塊中的代碼也將被執(zhí)行。
using System; class MyException { public static void Main() { int x = 0; int div = 0; try { div = 100/x; Console.WriteLine("此行未執(zhí)行"); } catch(DivideByZeroException) { Console.WriteLine("發(fā)生異常"); } finally { Console.WriteLine("Finally塊"); } Console.WriteLine($"結(jié)果為 {div}"); } }
請(qǐng)記住,在C#中,catch塊是可選的。
以下程序在C#中是完全合法的。
using System; class MyException { public static void Main() { int x = 0; int div = 0; try { div = 100/x; Console.WriteLine("此行未執(zhí)行"); } finally { Console.WriteLine("Finally塊"); } Console.WriteLine($"結(jié)果為 {div}"); } }
但是在這種情況下,由于沒有異常處理catch塊,因此執(zhí)行將終止。
但是在終止程序語句之前,finally塊中的語句將得到執(zhí)行。
在C#中,try塊之后必須是catch或finally塊。
多個(gè)catch塊
一個(gè)try塊可以引發(fā)多個(gè)異常,可以使用多個(gè)catch塊來處理。
記住,在通用的catch 塊之前應(yīng)該有更專業(yè)的catch 塊。否則,編譯器將顯示編譯錯(cuò)誤。
using System; class MyException { public static void Main() { int x = 0; int div = 0; try { div = 100 / x; Console.WriteLine("此行未執(zhí)行"); } catch (DivideByZeroException de) { Console.WriteLine("DivideByZeroException"); } catch (Exception) { Console.WriteLine("Exception"); } finally { Console.WriteLine("Finally塊"); } Console.WriteLine($"結(jié)果為 {div}"); } }
捕獲所有異常
通過提供沒有方括號(hào)或參數(shù)的catch塊,我們可以捕獲try塊內(nèi)發(fā)生的所有異常。
即使我們可以使用帶有Exception類型參數(shù)的catch塊來捕獲try塊內(nèi)發(fā)生的所有異常,因?yàn)樵贑#中,所有異常都直接或間接地從Exception類繼承。
using System; class MyException { public static void Main() { int x = 0; int div = 0; try { div = 100 / x; Console.WriteLine("此行未執(zhí)行"); } catch { Console.WriteLine("oException"); } Console.WriteLine($"結(jié)果為 {div}"); } }
以下程序使用Exception對(duì)象處理所有異常。
using System; class MyException { public static void Main() { int x = 0; int div = 0; try { div = 100 / x; Console.WriteLine("此行未執(zhí)行"); } catch (Exception) { Console.WriteLine("oException"); } Console.WriteLine($"結(jié)果為 {div}"); } }
引發(fā)異常
在C#中,可以以編程方式引發(fā)異常。為此,使用了“ throw”關(guān)鍵字。引發(fā)異常的一般形式如下。
throw exception_obj;
例如,以下語句顯式引發(fā)ArgumentException。
throw new ArgumentException("Exception"); using System; class MyException { public static void Main() { try { throw new DivideByZeroException("Invalid Division"); } catch (DivideByZeroException) { Console.WriteLine("Exception"); } Console.WriteLine("LAST STATEMENT"); } }
重新拋出異常(throw)
我們?cè)赾atch塊內(nèi)捕獲的異??梢酝ㄟ^使用catch塊內(nèi)的關(guān)鍵字throw來重新拋出更高的上下文。
以下程序顯示了如何執(zhí)行此操作。
//C#: Exception Handling: Handling all exceptions using System; class MyClass { public void Method() { try { int x = 0; int sum = 100 / x; } catch (DivideByZeroException) { throw; } } } class MyException { public static void Main() { MyClass mc = new MyClass(); try { mc.Method(); } catch (Exception) { Console.WriteLine("此處捕獲異常"); } Console.WriteLine("LAST STATEMENT"); } }
標(biāo)準(zhǔn)例外
異常有兩種類型:由執(zhí)行程序生成的異常和由公共語言運(yùn)行時(shí)生成的異常。
System.Exception是C#中所有異常的基類。多個(gè)異常類從該類繼承,包括ApplicationException和SystemException。
這兩個(gè)類構(gòu)成了大多數(shù)其他運(yùn)行時(shí)異常的基礎(chǔ)。直接從System.Exception派生的其他異常包括IOException,WebException等。
公共語言運(yùn)行庫引發(fā)SystemException。ApplicationException由用戶程序而不是運(yùn)行時(shí)引發(fā)。
SystemException包括ExecutionEngineException,StaclOverFlowException等。
不建議我們捕獲SystemException,也不建議在我們的應(yīng)用程序中拋出SystemException。
- System.OutOfMemoryException
- System.NullReferenceException
- Syste.InvalidCastException
- Syste.ArrayTypeMismatchException
- System.IndexOutOfRangeException
- System.ArithmeticException
- System.DevideByZeroException
- System.OverFlowException
用戶定義的異常
在C#中,可以創(chuàng)建我們自己的異常類。但是Exception必須是C#中所有異常的最終基類。
因此,用戶定義的異常類必須從Exception類或其標(biāo)準(zhǔn)派生類之一繼承。
using System; //用戶自定義的異常 class CustomException : Exception { public CustomException(string str) { Console.WriteLine("用戶定義的異常"); } } class MyException { public static void Main() { try { throw new CustomException("RAJESH"); } catch (Exception e) { Console.WriteLine("此處捕獲異常" + e.ToString()); } Console.WriteLine("LAST STATEMENT"); } }
設(shè)計(jì)準(zhǔn)則
異常應(yīng)用于傳達(dá)特殊情況。不要使用它們來傳達(dá)預(yù)期的事件,例如到達(dá)文件末尾。
如果在System命名空間中有一個(gè)很好的預(yù)定義異常,它描述了異常情況——一個(gè)對(duì)類的用戶有意義的——使用該類而不是定義一個(gè)新的異常類,并在消息中放入特定的信息。
最后,如果代碼捕獲到了將要處理的異常,請(qǐng)?jiān)谥匦聮伋鲈摦惓V翱紤]是否應(yīng)將異常與其他信息一起包裝。
try中的return語句先于finally中的函數(shù)執(zhí)行
代碼如下:
static void Main(string[] args) { Console.WriteLine(GetNum()); } public static int GetNum() { int Num=1; try { Console.WriteLine("try"); return Num; } catch (Exception ex) { throw ex; } finally { ++Num; Console.WriteLine("finally"); } }
輸出結(jié)果如下:
結(jié)論
try中的return語句先于finally中的函數(shù)執(zhí)行所以,返回的結(jié)果是1, 而不是2。
從運(yùn)行結(jié)果可以看出,return語句執(zhí)行后,將把返回結(jié)果放置進(jìn)函數(shù)棧中,此時(shí)函數(shù)并不是馬上返回,它要執(zhí)行finally語句后才真正開始返回。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#使用游標(biāo)實(shí)現(xiàn)補(bǔ)間函數(shù)
這篇文章主要為大家詳細(xì)介紹了C#使用游標(biāo)實(shí)現(xiàn)補(bǔ)間函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn)
這篇文章主要介紹了C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02C#將隱私信息(銀行賬戶,身份證號(hào)碼)中間部分特殊字符替換成*
大家在銀行交易某些業(yè)務(wù)時(shí),都可以看到無論是身份證、銀行賬號(hào)中間部分都是用*號(hào)替換的,下面這篇文章主要介紹C#將隱私信息(銀行賬戶,身份證號(hào)碼)中間部分特殊字符替換成*的相關(guān)資料,需要的朋友可以參考下2015-08-08