例外狀況Exceptions

在 C# 中的例外狀況會提供結構化、 統一和型別安全的方式來處理系統層級和應用程式層級錯誤狀況。Exceptions in C# provide a structured, uniform, and type-safe way of handling both system level and application level error conditions. 中的例外狀況機制C#是相當類似於C++,但有一些重要差異:The exception mechanism in C# is quite similar to that of C++, with a few important differences:

  • 在 C# 中,所有例外狀況必須衍生自的類別類型的執行個體所表示System.ExceptionIn C#, all exceptions must be represented by an instance of a class type derived from System.Exception. 在C++,任何型別的任何值可用來表示例外狀況。In C++, any value of any type can be used to represent an exception.
  • 在 C# 中,finally 區塊 (try 陳述式) 可用來撰寫一般執行和例外狀況中執行的終止程式碼。In C#, a finally block (The try statement) can be used to write termination code that executes in both normal execution and exceptional conditions. 這類程式碼很難撰寫C++不含重複的程式碼。Such code is difficult to write in C++ without duplicating code.
  • 在 C# 中,系統層級例外狀況例如溢位、 除數為零和 null 取值也定義了例外狀況類別和應用程式層級錯誤狀況與同等。In C#, system-level exceptions such as overflow, divide-by-zero, and null dereferences have well defined exception classes and are on a par with application-level error conditions.

例外狀況的原因Causes of exceptions

兩個不同的方式,可以擲回例外狀況。Exception can be thrown in two different ways.

  • Athrow陳述式 (throw 陳述式) 立即且無條件地擲回例外狀況。A throw statement (The throw statement) throws an exception immediately and unconditionally. 控制永遠不會到達緊接throwControl never reaches the statement immediately following the throw.
  • 某些 C# 陳述式和運算式的處理期間所發生的例外狀況會導致在某些情況下發生例外狀況時無法正常完成的作業。Certain exceptional conditions that arise during the processing of C# statements and expression cause an exception in certain circumstances when the operation cannot be completed normally. 例如,整數除法運算 (除法運算子) 會擲回System.DivideByZeroException如果分母為零。For example, an integer division operation (Division operator) throws a System.DivideByZeroException if the denominator is zero. 請參閱常見的例外狀況類別取得一份可能會發生這種方式的各種例外狀況。See Common Exception Classes for a list of the various exceptions that can occur in this way.

System.Exception 類別The System.Exception class

System.Exception類別是所有例外狀況的基底類型。The System.Exception class is the base type of all exceptions. 這個類別會有共用的所有例外狀況的幾個重要屬性:This class has a few notable properties that all exceptions share:

  • Message 是唯讀的屬性型別的string,包含人類看得懂的例外狀況的原因描述。Message is a read-only property of type string that contains a human-readable description of the reason for the exception.
  • InnerException 是唯讀的屬性型別的ExceptionInnerException is a read-only property of type Exception. 如果其值為非 null,它是指造成目前例外狀況的例外狀況,也就是在 catch 區塊中引發目前的例外狀況處理InnerExceptionIf its value is non-null, it refers to the exception that caused the current exception—that is, the current exception was raised in a catch block handling the InnerException. 否則,其值為 null,表示這個例外狀況不是由另一個例外狀況所造成的。Otherwise, its value is null, indicating that this exception was not caused by another exception. 以這種方式鏈結在一起的例外狀況物件的數目可以是任意的。The number of exception objects chained together in this manner can be arbitrary.

這些屬性的值可以指定的執行個體建構函式的呼叫中System.ExceptionThe value of these properties can be specified in calls to the instance constructor for System.Exception.

如何處理例外狀況How exceptions are handled

例外狀況會由try陳述式 (try 陳述式)。Exceptions are handled by a try statement (The try statement).

發生例外狀況時,系統會搜尋最接近catch可以處理例外狀況,例外狀況的執行階段型別所決定的子句。When an exception occurs, the system searches for the nearest catch clause that can handle the exception, as determined by the run-time type of the exception. 首先,目前的方法搜尋語彙封閉式try陳述式和相關聯的 catch 子句的 try 陳述式會被視為順序。First, the current method is searched for a lexically enclosing try statement, and the associated catch clauses of the try statement are considered in order. 如果失敗,請呼叫目前方法的方法會搜尋語彙封閉式try目前方法的呼叫點封入陳述式。If that fails, the method that called the current method is searched for a lexically enclosing try statement that encloses the point of the call to the current method. 此搜尋會繼續直到catch子句找到可以處理目前的例外狀況,藉由命名為相同的類別或基底類別之型別的執行階段擲回例外狀況的例外狀況類別。This search continues until a catch clause is found that can handle the current exception, by naming an exception class that is of the same class, or a base class, of the run-time type of the exception being thrown. Acatch子句未命名的例外狀況類別可以處理任何例外狀況。A catch clause that doesn't name an exception class can handle any exception.

一旦找到相符的 catch 子句,系統會將控制權轉移到 catch 子句的第一個陳述式準備。Once a matching catch clause is found, the system prepares to transfer control to the first statement of the catch clause. Catch 子句執行開始之前,系統會先執行,依序任何finally子句所需的 try 陳述式相關聯的巢狀,比攔截到例外狀況。Before execution of the catch clause begins, the system first executes, in order, any finally clauses that were associated with try statements more nested that than the one that caught the exception.

如果不找到任何相符的 catch 子句,就會發生下列其中一種:If no matching catch clause is found, one of two things occurs:

  • 如果搜尋相符的 catch 子句已達到靜態建構函式 (靜態建構函式) 或靜態欄位初始設定式,則會顯示System.TypeInitializationException觸發靜態建構函式的引動過程之處擲回。If the search for a matching catch clause reaches a static constructor (Static constructors) or static field initializer, then a System.TypeInitializationException is thrown at the point that triggered the invocation of the static constructor. 內部例外狀況的System.TypeInitializationException包含原先擲回的例外狀況。The inner exception of the System.TypeInitializationException contains the exception that was originally thrown.
  • 如果比對 catch 子句的搜尋已達到執行緒的初始啟動的程式碼,然後會終止執行緒的執行。If the search for matching catch clauses reaches the code that initially started the thread, then execution of the thread is terminated. 這類終止的影響是由實作定義。The impact of such termination is implementation-defined.

解構函式執行期間所發生的例外狀況是值得特別一提。Exceptions that occur during destructor execution are worth special mention. 如果解構函式執行期間發生的例外狀況,而且未攔截到例外狀況,然後該解構函式的執行已終止,並 (如果有的話) 的基底類別的解構函式呼叫。If an exception occurs during destructor execution, and that exception is not caught, then the execution of that destructor is terminated and the destructor of the base class (if any) is called. 如果沒有基底類別 (如果是做為object型別) 或如果沒有基底類別解構函式,則會捨棄例外狀況。If there is no base class (as in the case of the object type) or if there is no base class destructor, then the exception is discarded.

常見的例外狀況類別Common Exception Classes

某些 C# 作業會擲回下列例外狀況。The following exceptions are thrown by certain C# operations.

System.ArithmeticException 在算術運算期間所發生的例外狀況 (例如 System.DivideByZeroExceptionSystem.OverflowException) 的基底類別。A base class for exceptions that occur during arithmetic operations, such as System.DivideByZeroException and System.OverflowException.
System.ArrayTypeMismatchException 陣列的存放區失敗,因為實際的預存的項目類型是與陣列的實際型別不相容時,便會擲回。Thrown when a store into an array fails because the actual type of the stored element is incompatible with the actual type of the array.
System.DivideByZeroException 當發生除以零的整數值的嘗試時,便會擲回。Thrown when an attempt to divide an integral value by zero occurs.
System.IndexOutOfRangeException 當嘗試透過索引小於零或超出陣列界限的陣列編製索引時,便會擲回。Thrown when an attempt to index an array via an index that is less than zero or outside the bounds of the array.
System.InvalidCastException 基底類型或介面從衍生類型的明確轉換在執行階段失敗時擲回。Thrown when an explicit conversion from a base type or interface to a derived type fails at run time.
System.NullReferenceException 時擲回null參考會在讓需要參考的物件。Thrown when a null reference is used in a way that causes the referenced object to be required.
System.OutOfMemoryException 當嘗試配置記憶體時擲回 (透過new) 就會失敗。Thrown when an attempt to allocate memory (via new) fails.
System.OverflowException checked 內容中的算術運算溢位時擲回。Thrown when an arithmetic operation in a checked context overflows.
System.StackOverflowException 當有太多暫止方法呼叫; 耗盡執行堆疊時擲回通常是用來指示非常深或無限遞迴。Thrown when the execution stack is exhausted by having too many pending method calls; typically indicative of very deep or unbounded recursion.
System.TypeInitializationException 靜態建構函式會擲回例外狀況,但不含任何時擲回catch子句存在攔截它。Thrown when a static constructor throws an exception, and no catch clauses exists to catch it.