全國(guó)網(wǎng)站建設(shè)優(yōu)化設(shè)計(jì)的答案
在 C# 中,程序中的運(yùn)行時(shí)錯(cuò)誤通過(guò)使用一種稱(chēng)為“異?!钡臋C(jī)制在程序中傳播。 異常由遇到錯(cuò)誤的代碼引發(fā),由能夠更正錯(cuò)誤的代碼捕捉。 異??捎?.NET 運(yùn)行時(shí)或由程序中的代碼引發(fā)。 一旦引發(fā)了一個(gè)異常,此異常會(huì)在調(diào)用堆棧中傳播,直到找到針對(duì)它的 catch 語(yǔ)句。 未捕獲的異常由系統(tǒng)提供的通用異常處理程序處理,該處理程序會(huì)顯示一個(gè)對(duì)話框。
異常由從 Exception 派生的類(lèi)表示。 此類(lèi)標(biāo)識(shí)異常的類(lèi)型,并包含詳細(xì)描述異常的屬性。 引發(fā)異常涉及創(chuàng)建異常派生類(lèi)的實(shí)例,配置異常的屬性(可選),然后使用 throw 關(guān)鍵字引發(fā)該對(duì)象。 例如:
class CustomException : Exception
{public CustomException(string message){}
}
private static void TestThrow()
{throw new CustomException("Custom exception in TestThrow()");
}
引發(fā)異常后,運(yùn)行時(shí)將檢查當(dāng)前語(yǔ)句,以確定它是否在 try 塊內(nèi)。 如果在,則將檢查與 try 塊關(guān)聯(lián)的所有 catch 塊,以確定它們是否可以捕獲該異常。 Catch 塊通常會(huì)指定異常類(lèi)型;如果該 catch 塊的類(lèi)型與異?;虍惓5幕?lèi)的類(lèi)型相同,則該 catch 塊可處理該方法。 例如:
try
{TestThrow();
}
catch (CustomException ex)
{System.Console.WriteLine(ex.ToString());
}
如果引發(fā)異常的語(yǔ)句不在 try 塊內(nèi)或者包含該語(yǔ)句的 try 塊沒(méi)有匹配的 catch 塊,則運(yùn)行時(shí)將檢查調(diào)用方法中是否有 try 語(yǔ)句和 catch 塊。 運(yùn)行時(shí)將繼續(xù)調(diào)用堆棧,搜索兼容的 catch 塊。 在找到并執(zhí)行 catch 塊之后,控制權(quán)將傳遞給 catch 塊之后的下一個(gè)語(yǔ)句。
一個(gè) try 語(yǔ)句可包含多個(gè) catch 塊。 將執(zhí)行第一個(gè)能夠處理該異常的 catch 語(yǔ)句;將忽略任何后續(xù)的 catch 語(yǔ)句,即使它們是兼容的也是如此。 按從最具有針對(duì)性(或派生程度最高)到最不具有針對(duì)性的順序?qū)?catch 塊排列。 例如:
using System;
using System.IO;namespace Exceptions
{public class CatchOrder{public static void Main(){try{using (var sw = new StreamWriter("./test.txt")){sw.WriteLine("Hello");}}// Put the more specific exceptions first.catch (DirectoryNotFoundException ex){Console.WriteLine(ex);}catch (FileNotFoundException ex){Console.WriteLine(ex);}// Put the least specific exception last.catch (IOException ex){Console.WriteLine(ex);}Console.WriteLine("Done");}}
}
執(zhí)行 catch 塊之前,運(yùn)行時(shí)會(huì)檢查 finally 塊。 Finally 塊使程序員可以清除中止的 try 塊可能遺留下的任何模糊狀態(tài),或者釋放任何外部資源(例如圖形句柄、數(shù)據(jù)庫(kù)連接或文件流),而無(wú)需等待垃圾回收器在運(yùn)行時(shí)完成這些對(duì)象。 例如:
static void TestFinally()
{FileStream? file = null;//Change the path to something that works on your machine.FileInfo fileInfo = new System.IO.FileInfo("./file.txt");try{file = fileInfo.OpenWrite();file.WriteByte(0xF);}finally{// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.file?.Close();}try{file = fileInfo.OpenWrite();Console.WriteLine("OpenWrite() succeeded");}catch (IOException){Console.WriteLine("OpenWrite() failed");}
}
如果 WriteByte() 引發(fā)了異常并且未調(diào)用 file.Close(),則第二個(gè) try 塊中嘗試重新打開(kāi)文件的代碼將會(huì)失敗,并且文件將保持鎖定狀態(tài)。 由于即使引發(fā)異常也會(huì)執(zhí)行 finally 塊,前一示例中的 finally 塊可使文件正確關(guān)閉,從而有助于避免錯(cuò)誤。
如果引發(fā)異常之后沒(méi)有在調(diào)用堆棧上找到兼容的 catch 塊,則會(huì)出現(xiàn)以下三種情況之一:
- 如果異常存在于終結(jié)器內(nèi),將中止終結(jié)器,并調(diào)用基類(lèi)終結(jié)器(如果有);
- 如果調(diào)用堆棧包含靜態(tài)構(gòu)造函數(shù)或靜態(tài)字段初始值設(shè)定項(xiàng),將引發(fā) TypeInitializationException,同時(shí)將原始異常分配給新異常的 InnerException 屬性;
- 如果到達(dá)線程的開(kāi)頭,則終止線程;