C#中的异常提供了一种结构化,统一且类型安全的方法来处理系统级和应用程序级错误条件。C#中的异常机制与C ++的异常机制非常相似,但有一些重要的区别:
- 在C#中,所有异常必须由派生自的类类型的实例表示
System.Exception
。在C ++中,任何类型的任何值都可用于表示异常。 - 在C#中,finally块(try语句)可用于编写在正常执行和异常条件下执行的终止代码。在没有重复代码的情况下,这样的代码很难用C ++编写。
- 在C#中,系统级异常(例如溢出,被零除和空取消引用)具有明确定义的异常类,并且与应用程序级错误条件相同。
异常的原因
可以通过两种不同的方式抛出异常。
- 一个
throw
声明(throw语句)立即无条件地抛出一个异常。控制永远不会达到紧随其后的声明throw
。 - 在处理C#语句和表达式期间出现的某些异常情况会导致在某些情况下无法正常完成操作时发生异常。例如,如果分母为零,则整数除法运算(除法运算符)抛出a
System.DivideByZeroException
。请参阅公共异常类以获取以这种方式可能发生的各种异常的列表。
System.Exception类
本System.Exception
类是所有异常的基本类型。此类有一些值得注意的属性,所有异常共享:
Message
是一个只读属性string
,包含对异常原因的人类可读描述。InnerException
是类型的只读属性Exception
。如果其值为非null,则它引用导致当前异常的异常 - 也就是说,当前异常是在处理该异常的catch块中引发的InnerException
。否则,其值为null,表示此异常不是由另一个异常引起的。以这种方式链接在一起的异常对象的数量可以是任意的。
可以在对实例构造函数的调用中指定这些属性的值System.Exception
。
如何处理异常
异常由try
语句(try语句)处理。
发生异常时,系统将搜索catch
可以处理异常的最近子句,具体由异常的运行时类型决定。首先,在当前方法中搜索词法封闭try
语句,并按顺序考虑try语句的关联catch子句。如果失败,则搜索调用当前方法的方法,以查找try
包含对当前方法的调用点的词法封闭语句。此搜索将继续,直到catch
找到可以处理当前异常的子句,方法是命名与抛出的异常的运行时类型相同的类或基类的异常类。一个catch
条款,没有指定的异常类可以处理任何异常。
一旦找到匹配的catch子句,系统就会准备将控制转移到catch子句的第一个语句。在执行catch子句开始之前,系统首先按顺序执行finally
与try语句关联的任何子句,这些子句比捕获该异常的语句更嵌套。
如果找不到匹配的catch子句,则会发生以下两种情况之一:
- 如果搜索匹配的catch子句到达静态构造函数(静态构造函数)或静态字段初始化程序,则会
System.TypeInitializationException
在触发静态构造函数调用的位置抛出a 。System.TypeInitializationException
包含最初抛出的异常的内部异常。 - 如果搜索匹配的catch子句到达最初启动该线程的代码,则终止执行该线程。这种终止的影响是实现定义的。
析构函数执行期间发生的异常值得特别提及。如果在析构函数执行期间发生异常,并且未捕获该异常,则终止该析构函数的执行并调用基类的析构函数(如果有)。如果没有基类(如object
类型的情况)或者没有基类析构函数,则抛弃该异常。
常见异常类
某些C#操作抛出以下异常。
System.ArithmeticException | 算术运算期间发生的异常的基类,例如System.DivideByZeroException 和System.OverflowException 。 |
System.ArrayTypeMismatchException | 当存储进入数组失败时抛出,因为存储元素的实际类型与数组的实际类型不兼容。 |
System.DivideByZeroException | 当尝试将积分值除以零时抛出。 |
System.IndexOutOfRangeException | 尝试通过小于零的索引或超出数组边界索引数组时抛出。 |
System.InvalidCastException | 在运行时从基类型或接口到派生类型的显式转换失败时抛出。 |
System.NullReferenceException | 当null 引用以导致需要引用对象的方式使用时抛出。 |
System.OutOfMemoryException | 尝试分配内存(via new )失败时抛出。 |
System.OverflowException | 当checked 上下文中的算术运算溢出时抛出。 |
System.StackOverflowException | 当执行堆栈因为有太多挂起的方法调用而耗尽时抛出; 通常表示非常深或无限递归。 |
System.TypeInitializationException | 当静态构造函数抛出异常时抛出,并且不catch 存在捕获它的子句。 |