异常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 # 中,可以使用 try 语句 (finally 块) 来编写在正常执行和异常情况下执行的终止代码。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 # 中,系统级别的异常(如溢出、被零除和空引用)具有定义完善的异常类,并且与应用程序级别的错误条件是同等的。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.

  • throw 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.DivideByZeroExceptionFor 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 语句,并按顺序考虑 try 语句的关联的 catch 子句。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. catch不命名异常类的子句可处理任何异常。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 与尝试语句相关联的、与捕获异常的子句更嵌套的所有子句。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.OverflowExceptionA 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 尝试通过) 分配内存 (失败时引发 newThrown 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.