異常處理四要素包括:一個表示異常詳細信息的類類型;一個向調用者引起異常類實例的成員;調用者的一段調用異常成員的代碼塊;調用者的一段處理將要發生異常的代碼塊。異常類類型包括:基類:System.Exception;系統級異常:System.SystemException;應用程序級異常:System.ApplicationException。html
(一).在.NET中有以下的異常類:數組
(1).由System.SystemException派生的異常類型:ide
System.AccessViolationException | 在試圖讀寫受保護內存時引起的異常。 |
System.ArgumentException | 在向方法提供的其中一個參數無效時引起的異常。 |
System.Collections.Generic.KeyNotFoundException | 指定用於訪問集合中元素的鍵與集合中的任何鍵都不匹配時所引起的異常。 |
System.IndexOutOfRangeException | 訪問數組時,因元素索引超出數組邊界而引起的異常。 |
System.InvalidCastException | 因無效類型轉換或顯示轉換引起的異常。 |
System.InvalidOperationException | 當方法調用對於對象的當前狀態無效時引起的異常。 |
System.InvalidProgramException | 當程序包含無效Microsoft中間語言(MSIL)或元數據時引起的異常,這一般表示生成程序的編譯器中有bug。 |
System.IO.IOException | 發生I/O錯誤時引起的異常。 |
System.NotImplementedException | 在沒法實現請求的方法或操做時引起的異常。 |
System.NullReferenceException | 嘗試對空對象引用進行操做時引起的異常。 |
System.OutOfMemoryException | 沒有足夠的內存繼續執行程序時引起的異常。 |
System.StackOverflowException | 掛起的方法調用過多而致使執行堆棧溢出時引起的異常。 |
(2).由System.ArgumentException派生的異常類型:post
System.ArgumentNullException | 當將空引用傳遞給不接受它做爲有效參數的方法時引起的異常。 |
System.ArgumentOutOfRangeException | 當參數值超出調用的方法所定義的容許取值範圍時引起的異常。 |
(3).由System.ArithmeticException派生的異常類型:測試
System.DivideByZeroException | 試圖用零除整數值或十進制數值時引起的異常。 |
System.NotFiniteNumberException | 當浮點值爲正無窮大、負無窮大或非數字(NaN)時引起的異常。 |
System.OverflowException | 在選中的上下文中所進行的算數運算、類型轉換或轉換操做致使溢出時引起的異常。 |
(4).由System.IOException派生的異常類型:ui
System.IO.DirectoryNotFoundException | 當找不到文件或目錄的一部分時所引起的異常。 |
System.IO.DriveNotFoundException | 當嘗試訪問的驅動器或共享不可用時引起的異常。 |
System.IO.EndOfStreamException | 讀操做試圖超出流的末尾時引起的異常。 |
System.IO.FileLoadException | 當找到託管程序卻不能加載它時引起的異常。 |
System.IO.FileNotFoundException | 試圖訪問磁盤上不存在的文件失敗時引起的異常。 |
System.IO.PathTooLongException | 當路徑名或文件名超過系統定義的最大長度時引起的異常。 |
(5).其餘經常使用異常類型: this
ArrayTypeMismatchException | 試圖在數組中存儲錯誤類型的對象。 |
BadImageFormatException | 圖形的格式錯誤。 |
DivideByZeroException | 除零異常。 |
DllNotFoundException | 找不到引用的dll。 |
FormatException | 參數格式錯誤。 |
MethodAccessException | 試圖訪問私有或者受保護的方法。 |
MissingMemberException | 訪問一個無效版本的dll。 |
NotSupportedException | 調用的方法在類中沒有實現。 |
PlatformNotSupportedException | 平臺不支持某個特定屬性時拋出該錯誤。 |
(二)..NET的異常處理方式:url
發生異常時,系統將搜索能夠處理該異常的最近的 catch 子句(根據該異常的運行時類型來肯定)。首先,搜索當前的方法以查找一個詞法上包含着它的 try 語句,並按順序考察與該 try 語句相關聯的各個 catch 子句。若是上述操做失敗,則在調用了當前方法的方法中,搜索在詞法上包含着當前方法調用代碼位置的 try 語句。此搜索將一直進行下去,直到找到能夠處理當前異常的 catch 子句(該子句指定一個異常類,它與當前引起該異常的運行時類型屬於同一個類或是該運行時類型所屬類的一個基類)。注意,沒有指定異常類的 catch 子句能夠處理任何異常。spa
找到匹配的 catch 子句後,系統將把控制轉移到該 catch 子句的第一條語句。在 catch 子句的執行開始前,系統將首先按順序執行嵌套在捕捉到該異常的 try 語句裏面的全部 try 語句所對應的所有 finally 子句。線程
(1).try塊:包含的代碼一般須要執行一些通用的資源清理操做,或者須要從異常中恢復,或者二者都須要。try塊還能夠包含也許會拋出異常的代碼。
(2).catch塊:包含的是響應一個異常須要執行的代碼。若是沒有任何捕捉類型與拋出的異常匹配,CLR會去調用棧的更高一層搜索一個與異常匹配的捕捉類型。
(3).finally塊:包含的代碼是保證會執行的代碼。finally塊全部代碼執行完畢後,線程退出finally塊,執行緊跟在finally塊以後的語句。
(三).Exception的經常使用屬性的源碼解析:
(1).Message:包含輔助性文字說明,指出拋出異常的緣由。
public virtual String Message { get { if (_message == null) { if (_className==null) { _className = GetClassName(); } return Environment.GetRuntimeResourceString("Exception_WasThrown", _className); } else { return _message; } } }
(2).Data:對一個「鍵/值對」集合的引用。
public virtual IDictionary Data { [System.Security.SecuritySafeCritical] // auto-generated get { if (_data == null) if (IsImmutableAgileException(this)) _data = new EmptyReadOnlyDictionaryInternal(); else _data = new ListDictionaryInternal(); return _data; } }
(3).Source:包含生成異常的程序集名稱。
public virtual String Source { #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif get { if (_source == null) { StackTrace st = new StackTrace(this,true); if (st.FrameCount>0) { StackFrame sf = st.GetFrame(0); MethodBase method = sf.GetMethod(); Module module = method.Module; RuntimeModule rtModule = module as RuntimeModule; if (rtModule == null) { System.Reflection.Emit.ModuleBuilder moduleBuilder = module as System.Reflection.Emit.ModuleBuilder; if (moduleBuilder != null) rtModule = moduleBuilder.InternalModule; else throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeReflectionObject")); } _source = rtModule.GetRuntimeAssembly().GetSimpleName(); } } return _source; } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif set { _source = value; } }
(四).異常處理的經常使用方法:
(1).提取異常及其內部異常堆棧跟蹤
/// <summary> /// 提取異常及其內部異常堆棧跟蹤 /// </summary> /// <param name="exception">提取的例外</param> /// <param name="lastStackTrace">最後提取的堆棧跟蹤(對於遞歸), String.Empty or null</param> /// <param name="exCount">提取的堆棧數(對於遞歸)</param> /// <returns>Syste.String</returns> public static string ExtractAllStackTrace(this Exception exception, string lastStackTrace = null, int exCount = 1) { var ex = exception; const string entryFormat = "#{0}: {1}\r\n{2}"; //修復最後一個堆棧跟蹤參數 lastStackTrace = lastStackTrace ?? string.Empty; //添加異常的堆棧跟蹤 lastStackTrace += string.Format(entryFormat, exCount, ex.Message, ex.StackTrace); if (exception.Data.Count > 0) { lastStackTrace += "\r\n Data: "; foreach (var item in exception.Data) { var entry = (DictionaryEntry)item; lastStackTrace += string.Format("\r\n\t{0}: {1}", entry.Key, exception.Data[entry.Key]); } } //遞歸添加內部異常 if ((ex = ex.InnerException) != null) return ex.ExtractAllStackTrace(string.Format("{0}\r\n\r\n", lastStackTrace), ++exCount); return lastStackTrace; }
(2).檢查字符串是空的或空的,並拋出一個異常
/// <summary> /// 檢查字符串是空的或空的,並拋出一個異常 /// </summary> /// <param name="val">值測試</param> /// <param name="paramName">參數檢查名稱</param> public static void CheckNullOrEmpty(string val, string paramName) { if (string.IsNullOrEmpty(val)) throw new ArgumentNullException(paramName, "Value can't be null or empty"); }
(3).檢查參數不是無效,並拋出一個異常
/// <summary> /// 檢查參數不是無效,並拋出一個異常 /// </summary> /// <param name="param">檢查值</param> /// <param name="paramName">參數名稱</param> public static void CheckNullParam(object param, string paramName) { if (param == null) throw new ArgumentNullException(paramName, paramName + " can't be null"); }
(4).請檢查參數1不一樣於參數2
/// <summary> /// 請檢查參數1不一樣於參數2 /// </summary> /// <param name="param1">值1測試</param> /// <param name="param1Name">name of value 1</param> /// <param name="param2">value 2 to test</param> /// <param name="param2Name">name of vlaue 2</param> public static void CheckDifferentsParams(object param1, string param1Name, object param2, string param2Name) { if (param1 == param2) { throw new ArgumentException(param1Name + " can't be the same as " + param2Name, param1Name + " and " + param2Name); } }
(5).檢查一個整數值是正的(0或更大)
/// <summary> /// 檢查一個整數值是正的(0或更大) /// </summary> /// <param name="val">整數測試</param> public static void PositiveValue(int val) { if (val < 0) throw new ArgumentException("The value must be greater than or equal to 0."); }
異常處理器(程序):對於程序中出現的異常,在C#中是使用一種被稱爲「異常處理器(程序)」的錯誤捕獲機制來進行處理的, 你能夠認爲異常處理器(程序)就是發生錯誤時,可以接受並處理錯誤的接受者和處理。