一文 詳解C#正確使用異常的六大原則
前言
嗨,大家好!
編程的世界充滿了挑戰(zhàn)和樂(lè)趣,異常就是我們繞不過(guò)去的大石頭。
有時(shí)候,我們需要主動(dòng)引發(fā)一些異常;
有時(shí)候,我們又需要主動(dòng)捕捉一些異常;
有時(shí)候,我們還需要學(xué)會(huì)消滅一些異常;
……
所以,我們需要一套異常使用原則來(lái)幫助我們穩(wěn)住船舶,不讓意外攪亂了我們的編程節(jié)奏!
今天,我們就來(lái)聊聊六個(gè)關(guān)于異常使用的黃金法則,幫助你在這個(gè)充滿挑戰(zhàn)的領(lǐng)域中游刃有余。
六大原則
1. 不要對(duì)在可控范圍內(nèi)的輸入和輸出引發(fā)異常
這個(gè)原則的意思是,
在編寫(xiě)代碼時(shí),如果某些輸入或輸出是你可以預(yù)見(jiàn)并且可以控制的,就不要引發(fā)異常。
想象一下,你正在編寫(xiě)一個(gè)計(jì)算器應(yīng)用程序。
用戶輸入了兩個(gè)數(shù)字,你準(zhǔn)備進(jìn)行除法運(yùn)算。如果用戶輸入的除數(shù)是零,你會(huì)怎么做?拋出異常嗎?
不!在這種情況下,你可以簡(jiǎn)單地返回一個(gè)錯(cuò)誤消息,或者提示用戶重新輸入。
因?yàn)?,用戶輸入零是可控的,沒(méi)必要大驚小怪。
public int Divide(int a, int b)
{
if (b == 0)
{
Console.WriteLine("分母不能為零,請(qǐng)檢查輸入!");
return 0; // 或者其他合理的默認(rèn)值
}
return a / b;
}
2. 正常的業(yè)務(wù)流程盡可能不要使用異常來(lái)處理
假設(shè)你正在編寫(xiě)一個(gè)電商網(wǎng)站的訂單處理系統(tǒng)。
如果用戶嘗試購(gòu)買(mǎi)一個(gè)已經(jīng)售罄的商品,你會(huì)拋出異常嗎?
當(dāng)然不!
你可以簡(jiǎn)單地返回一個(gè)“商品已售罄”的消息,或者將用戶引導(dǎo)到其他商品頁(yè)面,因?yàn)檫@是一個(gè)正常的業(yè)務(wù)邏輯。
異常是用來(lái)處理意外情況的,而不是用來(lái)處理正常的業(yè)務(wù)流程。
// 錯(cuò)誤示范
try
{
var result = GetProductById(productId);
}
catch (NullReferenceException ex)
{
// 處理商品不存在的情況
}
// 更好的做法
var product = GetProductById(productId);
if (product == null)
{
Console.WriteLine("當(dāng)前商品已售罄");
// 引導(dǎo)到其他商品頁(yè)面
}
3. 不要總是嘗試去捕獲異常,允許異常往上傳播
假設(shè)你正在編寫(xiě)一個(gè)底層的文件處理程序。
如果文件讀取失敗,你需要立即捕獲異常并處理嗎?不一定!
有時(shí)候,讓異常向上傳播到更高層的代碼中處理可能更合適。
這樣,你可以集中處理異常,而不是在每個(gè)方法中都進(jìn)行捕獲。
public void FileHandler()
{
try
{
ReadFile();
}
catch (Exception ex)
{
throw; // 讓異常往上傳播
}
}
4. 如果運(yùn)行代碼后,會(huì)造成內(nèi)存泄漏、資源不可用,或者應(yīng)用程序狀態(tài)不可恢復(fù),則引發(fā)異常
假設(shè)你正在編寫(xiě)一個(gè)很占內(nèi)存的操作。
如果操作可以導(dǎo)致內(nèi)存占用過(guò)高,你會(huì)怎么做?拋出異常!因?yàn)槿绻麅?nèi)存占用過(guò)高,應(yīng)用程序的狀態(tài)將不可恢復(fù)。
在這種情況下,拋出異常是必要的。
List<byte[]> memoryLeakList = new List<byte[]>();
long memoryThreshold = 1024 * 1024 * 100;
while (true)
{
byte[] buffer = new byte[1024 * 1024];
memoryLeakList.Add(buffer);
if (GC.GetTotalMemory(false) > memoryThreshold)
{
throw new OutOfMemoryException("內(nèi)存使用超過(guò)閾值,可能導(dǎo)致內(nèi)存泄漏或應(yīng)用程序狀態(tài)不可恢復(fù)。");
}
Thread.Sleep(100);
}
5. 在捕獲異常的時(shí)候,如果需要包裝一些更有用的信息,則引發(fā)異常
這類異常的引發(fā)在 UI 層特別有用。
系統(tǒng)引用的異常所帶的信息往往更傾向于技術(shù)性的描述;
而在 UI 層,面對(duì)異常的很可能是最終普通用戶,所以如果需要將異常的信息呈現(xiàn)給最終用戶,更好的做法明顯是先包裝異常,然后引發(fā)一個(gè)包含友好信息的新異常。
try
{
MyOperation();
}
catch (FileNotFoundException ex)
{
throw new FileNotFoundException($"無(wú)法找到指定的文件: {ex.FileName}", ex);
}
6. 如果底層異常在高層操作的上下文中沒(méi)有意義,那么在捕獲這些異常時(shí),引發(fā)新的有意義的異常
假設(shè)你正在調(diào)用 Windows API 或第三方 API 提供的接口時(shí),如果對(duì)方的異常報(bào)告機(jī)制使用的是錯(cuò)誤代碼,很不好理解,這時(shí)你會(huì)怎么辦?
最好的方法是重新引發(fā)該接口提供的錯(cuò)誤,創(chuàng)建一個(gè)新的更有意義的異常,因?yàn)槟阈枰寛F(tuán)隊(duì)更好地理解這些錯(cuò)誤。
int errorCode = CallApi();
if (errorCode == 6)
{
throw new FileNotFoundException($"文件路徑無(wú)效. [{path}]");
}
總結(jié)
在編程的世界里,異常處理是一門(mén)藝術(shù)。
本文我們一起探討了六個(gè)關(guān)于異常使用的黃金法則。
好的異常使用原則就像是為我們的代碼設(shè)置了安全帶。
記住,異常不是敵人,而是提示我們需要關(guān)注的地方。
到此這篇關(guān)于一文 詳解C#正確使用異常的六大原則的文章就介紹到這了,更多相關(guān)C#正確使用異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Unity使用LineRender實(shí)現(xiàn)繪畫(huà)功能
這篇文章主要為大家詳細(xì)介紹了Unity使用LineRender實(shí)現(xiàn)繪畫(huà)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
C#操作配置文件app.config、web.config增刪改
這篇文章介紹了C#操作配置文件app.config、web.config增刪改的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
C#中控制遠(yuǎn)程計(jì)算機(jī)的服務(wù)的方法
C#中控制遠(yuǎn)程計(jì)算機(jī)的服務(wù)的方法...2007-04-04
C#利用itext實(shí)現(xiàn)PDF頁(yè)面處理與切分
這篇文章主要介紹了如何在C#中使用itext做一個(gè)pdf的頁(yè)面大小一致性處理,然后再根據(jù)數(shù)據(jù)切分出需要的pdf,感興趣的小伙伴可以了解一下2022-04-04
深入分析C#中處理和鍵盤(pán)相關(guān)事件的詳解
本篇文章是對(duì)C#中處理和鍵盤(pán)相關(guān)的事件進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
c# 在windows中操作IIS設(shè)置FTP服務(wù)器的示例
這篇文章主要介紹了c# 在windows中操作IIS設(shè)置FTP服務(wù)器的示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03
C#中關(guān)于zip壓縮解壓幫助類的封裝 附源碼下載
之前一個(gè)同學(xué)問(wèn)了這個(gè)問(wèn)題后,看了園子里其它園友的封裝,都很零碎,調(diào)用也不是很方便。所以自己就封裝了一個(gè)zip解壓的類。后來(lái)想整理下怕自己忘了。就把壓縮的類也一并封裝了2013-02-02

