你應(yīng)該知道的.NET錯(cuò)誤與異常處理機(jī)制
前言
錯(cuò)誤的出現(xiàn)并不總是編寫程序的人的原因,有時(shí)應(yīng)用程序會(huì)因?yàn)閼?yīng)用程序的最終用戶引發(fā)的動(dòng)作或運(yùn)行代碼的環(huán)境發(fā)生錯(cuò)誤。無論如何,我們都應(yīng)預(yù)測(cè)應(yīng)用程序中出現(xiàn)的錯(cuò)誤,并相應(yīng)的進(jìn)行編碼。
.Net改進(jìn)了處理錯(cuò)誤的方式。C#處理錯(cuò)誤的機(jī)制可以為每種錯(cuò)誤提供自定義處理方式,并把識(shí)別錯(cuò)誤的代碼與處理錯(cuò)誤的代碼分別開來。
異常類
在C#中當(dāng)出現(xiàn)某個(gè)特殊的異常錯(cuò)誤條件時(shí),就會(huì)創(chuàng)建拋出一個(gè)異常對(duì)象,這個(gè)對(duì)象包含有助于跟蹤問題的信息。.Net提供了許多預(yù)定義的異常類,我們下面看看一些常見特別的異常類吧(異常類太多了,這里就介紹幾個(gè)常見的)。
對(duì)于.Net類,一般的異常類System.Exception派生自System.Object,通常不在代碼中拋出System.Exception泛型對(duì)象,因?yàn)樗麄儫o法確定錯(cuò)誤情況的本質(zhì)。
在該層次中有兩個(gè)重要的類,他們派生自System.Exception類:
- SystemException------該類用于通常由.NET允許庫(kù)拋出的異常,或者由幾乎所有的應(yīng)用程序拋出的異常。例如,如果.NET運(yùn)行庫(kù)檢測(cè)到棧已滿,他就會(huì)拋出StackOverflowException異常。另一方面,如果檢測(cè)到調(diào)用方法時(shí)參數(shù)不對(duì),就可以在自己的代碼中選擇拋出ArgumentException異?;蚱渥宇悺ystemException異常的子類包括表示致命錯(cuò)誤和非致命錯(cuò)誤的異常。
- ApplicationException----在.NET Framework最初的設(shè)計(jì)中,是打算把這個(gè)類作為自定義應(yīng)用程序異常類的基類的。不過,CLR拋出的一些異常類也派生自這個(gè)類。應(yīng)用程序拋出的異常則派生自SystemException。因此從ApplicationException派生自自定義異常類型沒有任何好處,取而代之的是,可以直接從Exception基類派生自定義異常類。
其他可能會(huì)用到的異常類包括:
- StackOverflowException-------如果分配給棧的內(nèi)存區(qū)域已滿,就會(huì)拋出這個(gè)異常。如果一個(gè)方法連續(xù)地遞歸調(diào)用自己,就可能發(fā)生棧溢出。這一般是一個(gè)致命錯(cuò)誤,因?yàn)樗箲?yīng)用程序執(zhí)行除了中斷以外的其他任務(wù)。在這種情況下,甚至也不可能執(zhí)行到finally塊。通常用戶自己不能處理像這樣的錯(cuò)誤,而應(yīng)退出應(yīng)用程序。
- EndOfStreamException-------這個(gè)異常通常是因?yàn)樽x到文件末尾而拋出的,流表示數(shù)據(jù)源之間的數(shù)據(jù)流。
- OverflowException-----如果要在checked上下文中把包含-40的int類型數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為uint數(shù)據(jù),就會(huì)拋出這個(gè)異常
- MemberAccessException----------該類用于處理訪問類的成員失敗時(shí)所引發(fā)的異常。失敗的原因可能的原因是沒有足夠的訪問權(quán)限,也可能是要訪問的成員根本不存在(類與類之間調(diào)用時(shí)常用)
- IndexOutOfException-------該類用于處理下標(biāo)超出了數(shù)組長(zhǎng)度所引發(fā)的異常
使用try...catch...finally捕獲異常
- try 塊包含的代碼組成了程序的正常操作部分,但這部分程序可能會(huì)遇到某些嚴(yán)重的錯(cuò)誤。
- catch塊包含的代碼處理各種錯(cuò)誤,這些錯(cuò)誤是執(zhí)行try塊中的代碼時(shí)遇到的問題。這個(gè)快可以用來記錄錯(cuò)誤。
- finally快包含的代碼清理資源或執(zhí)行通常要在try塊或者catch塊末尾執(zhí)行的其他操作。無論是否拋出異常,都會(huì)執(zhí)行finally塊。finally塊中防止return語句,編譯器會(huì)標(biāo)記一個(gè)錯(cuò)誤。另外此塊可以如果沒有需要關(guān)閉或者處理的其他操作可以省略此塊。
異常處理具有性能含義,在常見的情況下,不應(yīng)該使用異常處理錯(cuò)誤。應(yīng)盡量編寫好避免錯(cuò)誤出現(xiàn)的代碼。
在異常捕獲中,我們可以實(shí)現(xiàn)多個(gè)catch塊來針對(duì)不同的錯(cuò)誤做出對(duì)應(yīng)的錯(cuò)誤處理。下面我們看一個(gè)例子:
class Program { static void Main(string[] args) { while (true) { try { string userInput; Console.WriteLine("請(qǐng)輸入0-5之間任意一個(gè)數(shù)字:"); userInput = Console.ReadLine(); if (string.IsNullOrWhiteSpace(userInput)) { break; } if (int.TryParse(userInput, out int index)) { if (index < 0 || index > 5) { throw new IndexOutOfRangeException($"你輸入的數(shù)字是{index}"); } Console.WriteLine($"你輸入的數(shù)字是{index}"); } else { throw new Exception("請(qǐng)輸入數(shù)字"); } } catch (IndexOutOfRangeException ex) { Console.WriteLine($"你輸入的數(shù)字不在此范圍內(nèi).{ex.Message}"); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Console.WriteLine("謝謝合作"); } } } }
在此事例中,定義了兩個(gè)catch塊。如果輸入的超過規(guī)定返回的數(shù)字,則會(huì)拋出超出范圍的錯(cuò)誤也就進(jìn)入對(duì)應(yīng)的catch塊。而輸入的非數(shù)字也就進(jìn)入了另外一個(gè)catch塊進(jìn)行處理。
下面我們看一看關(guān)于System.Exception屬性。熟悉了解其中熟悉能更好的去觀察理解拋出的異常錯(cuò)誤。
屬性 |
說明 |
Data |
這個(gè)屬性可以給異常添加鍵/值語句,以提供關(guān)于異常的額外信息 |
HelpLink |
連接到一個(gè)幫助文件上,以提供關(guān)于該異常的更多信息 |
InnerException |
如果此異常是在catch塊中拋出的,它就會(huì)包含把代碼發(fā)送到catch塊的異常對(duì)象 |
Message |
描述錯(cuò)誤情況的文本 |
Source |
導(dǎo)致異常的應(yīng)用程序名或?qū)ο竺?/p> |
StackTrace |
棧上方法調(diào)用的詳細(xì)信息,它有助于跟蹤拋出異常的方法 |
Hresult |
分配給異常的一個(gè)數(shù)值 |
TargetSite |
.NET反射對(duì)象,描述了拋出異常的方法 |
過濾異常、創(chuàng)建用戶定義的異常
自從C#6開始就支持異常過濾器。Catch塊僅在過濾器但會(huì)true時(shí)執(zhí)行。捕獲不同的異常類型時(shí),可以有行為不同的代碼塊。在某些情況下,catch塊基于異常的內(nèi)容執(zhí)行不同的操作。下面我們看下如何來使用異常過濾器吧:
public class MyIndexOutOfException :SystemException { public MyIndexOutOfException(string message) : base(message) { } public int ErrorCode { get; set; } } class Program { static void Main(string[] args) { try { int steInput = 12; if (steInput > 10) { throw new MyIndexOutOfException("數(shù)據(jù)超出了范圍") { ErrorCode = 1 }; } } catch (MyIndexOutOfException ex) when (ex.ErrorCode!=1) { Console.WriteLine("出現(xiàn)了自定義錯(cuò)誤"); } catch (MyIndexOutOfException ex) when (ex.ErrorCode == 1) { Console.WriteLine(ex.Message); } catch (Exception ex) { throw; } } }
上面例子中,自定義了一個(gè)異常處理,同事增加ErrorCode,以此啦作為過濾條件,利用關(guān)鍵字When+條件來進(jìn)行過濾。
總結(jié)
本篇文章介紹了異常處理錯(cuò)誤的情況及機(jī)制,我們不僅可以輸出代碼好難過的一般錯(cuò)誤代碼,也可以輸出我們自己定義的特殊錯(cuò)誤情況。無論編程技術(shù)有多好,程序都必須能處理可能出現(xiàn)的任何錯(cuò)誤。對(duì)不同的錯(cuò)誤采取相應(yīng)的應(yīng)對(duì)措施,才是正確編碼的其中一步。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
.Net與JS時(shí)間日期格式的轉(zhuǎn)換問題對(duì)比分析
這篇文章主要介紹了.Net與JS時(shí)間日期格式的轉(zhuǎn)換問題,結(jié)合實(shí)例形式對(duì)比分析了JS與.Net針對(duì)時(shí)間日期格式的轉(zhuǎn)換處理相關(guān)技巧,需要的朋友可以參考下2016-08-08在ASP.NET Core中應(yīng)用HttpClient獲取數(shù)據(jù)和內(nèi)容
這篇文章主要介紹了在ASP.NET Core中集成和使用HttpClient獲取數(shù)據(jù)和內(nèi)容,幫助大家更好的理解和學(xué)習(xí)使用ASP.NET Core,感興趣的朋友可以了解下2021-03-03ASP.NET MVC獲取多級(jí)類別組合下的產(chǎn)品
這篇文章介紹了ASP.NET MVC獲取多級(jí)類別組合下產(chǎn)品的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09DataView.RowFilter的使用(包括in,like等SQL中的操作符)
這篇blog轉(zhuǎn)自C# examples,對(duì)DataView.RowFilter做了詳細(xì)介紹,能像SQL中使用in,like等操作符一樣進(jìn)行過濾查詢,并附有實(shí)例,使用方便。2011-07-07ASP.NET設(shè)置404頁(yè)面返回302HTTP狀態(tài)碼的解決方法
訪問網(wǎng)站時(shí)錯(cuò)誤頁(yè)面可正常顯示,但HTTP狀態(tài)碼卻是302,對(duì)SEO很不友好,按下列步驟修改使錯(cuò)誤頁(yè)面返回正確的利于SEO的404狀態(tài)碼,感興趣的朋友可以了解下2013-09-09解析WPF實(shí)現(xiàn)音頻文件循環(huán)順序播放的解決方法
本篇文章是對(duì)WPF實(shí)現(xiàn)音頻文件循環(huán)順序播放的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05