4.8.1 捕捉错误(2)
例如,假定用户输入的年龄是“forty-two”,那么int.Parse()会引发System.Format- Exception类型的一个异常,控制权会移交给后面的一系列catch块(System.FormatException表明字符串格式不正确,无法进行解析)。由于第一个catch块就与int.Parse()引发的异常类型匹配,所以会执行这个块中的代码。但假如try块中的语句引发的是一个不同类型的异常,那么执行的就是第二个catch块,因为几乎所有异常最终都属于System.Exception类型。
如果没有System.FormatException catch块,那么即使int.Parse引发的是一个System. FormatException异常,也会执行System.Exception catch块。这是由于System.Format- Exception也属于System.Exception类型(换言之,System.FormatException是泛化异常类System.Exception的一个更具体的子类)。
虽然catch块的数量可以随意,但处理异常的顺序千万不要随意。catch块必须按照从最具体到最不具体排列。System.Exception数据类型是最不具体的,所以它应该最后出现。System.Format- Exception排在第一,因为它是代码清单4-18所处理的最具体的异常。
无论try块中的代码是否引发一个异常,finally块都会执行。finally块的作用是提供一个最终位置,在其中放入无论是否发生异常都要执行的代码。finally块最适合用来执行资源清理。事实上,完全可以只写一个try块和一个finally块,而不写任何catch块。无论try块是否引发异常,甚至无论是否写了一个catch块来处理异常,finally块都会执行。代码清单4-19演示了一个try/finally块,输出4-14展示了结果。
代码清单4-19 捕捉异常
using System; class ExceptionHandling Console.Write("Enter your first name: "); Console.Write("Enter your age: ");try |
Enter your first name: Inigo Unhandled Exception: System.FormatException: Input string was not in a |
上述代码执行时会向用户显示一个未处理的异常,并执行finally块。
高级主题:Exception类继承
所有异常都派生自System.Exception类。所以,它们都可以用catch(System.Exception exception)块进行处理。然而,一个更好的做法是编写专门的catch块来处理更具体的派生类型(比如System.FormatException),从而获取有关异常的具体信息,有的放矢地进行处理,并避免使用
大量条件逻辑来判断具体发生了什么错误。
这正是C#规定catch块必须从“最具体”到“最不具体”排列的原因。例如,用于捕捉System. Exception的catch语句不能出现在捕捉
System.FormatException的catch语句之前,因为System.FormatException较System.Exception更加具体。
一个方法可以引发许多异常类型。表4-2总结了一些较为常见的类型。
表4-2 常见的异常类型
|
异常类型 |
描述 |
|
System.Exception |
这是最泛化的异常,其他所有异常 类型都从它派生 |
|
System.ArgumentException |
传给方法的一个参数无效 |
|
System.ArgumentNullException |
一个不应该为null的参数为null |
|
System.ApplicationException |
一个自定义的应用程序异常,开发者 可以用它标识特殊的、 非致命的应用程序错误 |
|
System.FormatException |
参数格式不符合调用的方法的参数规范 |
|
System.IndexOutOfRangeException |
试图访问一个不存在的数组元素 |
|
System.InvalidCastException |
因无效的类型转换或显式转换引发的异常 |
|
System.NotImplementedException |
虽然找到了对应的方法签名,但该方 法尚未完全实现 |
|
System.NullReferenceException |
试图访问尚未包含任何数据的一个变量 |
|
System.ArithmeticException |
发生了一个无效的数学运算,但其中不包括被零除 |
|
System.ArrayTypeMismatchException |
试图将类型有误的元素存储到数组中 |
|
System.StackOverflowException |
通常意味着一个无限循环,方法不停地回调自身(称为递归) |
高级主题:泛化catch
可以指定一个不获取任何参数的catch块,如代码清单4-20所示。
代码清单4-20 常规catch块
try |
没有指定数据类型的catch块称为泛化catch块(generic catch block),它等价于指定获取object数据类型的catch块,例如catch(object exception){...}。由于所有类最终都是从object派生,所以没有数据类型的catch块必须出现在最后。
泛化catch块很少使用,因为没有办法捕捉有关异常的任何信息。除此之外,C#不允许引发object类型的一个异常,只有使用C++这样的语言写的库才允许任意类型的异常。
C# 2.0中的行为稍微有别于之前版本的C#。在C# 2.0中,假如遇到用另一种语言写的代码,而且它会引发不是从System.Exception类派生的异常,那么该异常对象会被包装到一个System. Runtime.CompilerServices.RuntimeWrappedException中,后者是从System.Exception派生的。换言之,在C#程序集中,所有异常(无论它们是否从System.Exception派生)都会表现得和从System.Exception派生一样。
结果就是,用于捕捉System.Exception的catch块会捕捉之前的块没有捕捉到的所有异常, 同时,System.Exception catch块之后的一个常规catch块永远得不到调用。所以,在C# 2.0中,假如在捕捉System.Exception的catch块之后添加了一个常规catch块,编译器就会报告一条警告消息,指出常规catch块永远都不会执行。
| 回书目 上一节 下一节 |
|
||||
| · 龙芯要做中国的“奔腾” · 2008年上半年IT技术图.. · 虚拟化的“赤壁之战” · 服务器节能与绿色IT · 微软出价446亿美元收购.. · 脉冲无线电uwb专题 · 802.11n:下一代的无线.. · 云计算时代来临 |
· IT工程师该不该考CCIE.. · 浏览器的战国时代 · 2008年上半年全国软考.. · 无线网络环境 · 无线网状网(MESH) · 无线重中之重:安全问题 · 网络故障排除宝典 · Windows Server 2008专.. |
|||
|
||||
| · SOA 面向服务架构 · SQL Server 2008/2005.. · Apache技术专题 · 三层交换技术专题 · SQL Server入门到精通 · 无线网状网(MESH) · Windows远程桌面应用 · C#技术开发指南 |
· Apache技术专题 · Windows集群服务应用 · C#技术开发指南 · 文档格式标准开战 OOXM.. · 路由器设置与口令恢复 · Linux 集群技术专题 · PHP开发应用手册 · SOA 面向服务架构 |
|||
|
||||
| · SQL Server入门到精通 · SQL Server 2008/2005.. · SOA 面向服务架构 · Apache技术专题 · C#技术开发指南 · 三层交换技术专题 · Apache技术专题 · C#技术开发指南 |
· Windows远程桌面应用 · 企业数据恢复指南 · Windows集群服务应用 · 路由器设置与口令恢复 · Linux 集群技术专题 · SOA 面向服务架构 · 了解统一威胁管理(UTM).. · 解析35岁技术人的价值.. |
|||