频 道 直 达 - 新闻 - 培训 - 软件 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 读书 - 博客 - BBS
51CTO.COM_中国最大的网络技术网站
找资料:

4.8.1 捕捉错误(2)

作者: (美)米凯利斯(Michaelis, M.)著/周靖译 出处:人民邮电出版社  2008-07-20 09:44    砖    好    评论   进入论坛
阅读提示:《C#本质论》第2章数据类型,这一章将探讨基本的C#类型,继续学习C#的基础知识,本小节为大家介绍捕捉错误。

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
{
static int Main()
{
string firstName;
string ageText;
int age;
int result = 0;
      Console.Write("Enter your first name: ");
firstName = Console.ReadLine();
      Console.Write("Enter your age: ");
ageText = Console.ReadLine();
      try
{
age = int.Parse(ageText);
Console.WriteLine(
"Hi {0}! You are {1} months old.",
firstName, age*12);
}
finally
{
Console.WriteLine("Goodbye {0}",
firstName);
}
return result;
}
}
输出4-14
Enter your first name: Inigo
Enter your age: forty-two
Unhandled Exception: System.FormatException: Input string was not in a 
correct format.
at System.Number.StringToNumber(String str, NumberStyles options,
NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style,
NumberFormatInfo info)
at ExceptionHandling.Main()
Goodbye Inigo

上述代码执行时会向用户显示一个未处理的异常,并执行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
{
age = int.Parse(ageText);
System.Console.WriteLine(
"Hi {0}! You are {1} months old.",
firstName, age*12);
}
catch (System.FormatException exception)
{
System.Console.WriteLine(
"The age entered ,{0}, is not valid.",
ageText);
result = 1;
}
catch(System.Exception exception)
{
System.Console.WriteLine(
"Unexpected error: {0}", exception.Message);
result = 1;
}
catch
{
System.Console.WriteLine(
"Unexpected error!");
result = 1;
}
finally
{
System.Console.WriteLine("Goodbye {0}",
firstName);
}
...

没有指定数据类型的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块永远都不会执行。

【责任编辑:夏书 TEL:(010)68476606】

回书目   上一节   下一节
专题
程序员如何成长?
C#实用基础教程
C#技术开发指南
C#本质论
Windows Vista之兵法
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 最 大 的 网 络 技 术 网 站 ·
技 术 成 就 梦 想
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
CCNA认证考试Pass必备
CCNA认证考试Pass必备
求职必杀技 决战面试官
求职必杀技 决战面试官
龙芯要做中国的“奔腾”
龙芯要做中国的“奔腾”
· 龙芯要做中国的“奔腾”
· 2008年上半年IT技术图..
· 虚拟化的“赤壁之战”
· 服务器节能与绿色IT
· 微软出价446亿美元收购..
· 脉冲无线电uwb专题
· 802.11n:下一代的无线..
· 云计算时代来临
· IT工程师该不该考CCIE..
· 浏览器的战国时代
· 2008年上半年全国软考..
· 无线网络环境
· 无线网状网(MESH)
· 无线重中之重:安全问题
· 网络故障排除宝典
· Windows Server 2008专..
ARP攻击防范与解决方案
ARP攻击防范与解决方案
SQL Server 2008/2005全解
SQL Server 2008/2005全解
SOA 面向服务架构
SOA 面向服务架构
· SOA 面向服务架构
· SQL Server 2008/2005..
· Apache技术专题
· 三层交换技术专题
· SQL Server入门到精通
· 无线网状网(MESH)
· Windows远程桌面应用
· C#技术开发指南
· Apache技术专题
· Windows集群服务应用
· C#技术开发指南
· 文档格式标准开战 OOXM..
· 路由器设置与口令恢复
· Linux 集群技术专题
· PHP开发应用手册
· SOA 面向服务架构
ARP攻击防范与解决方案
ARP攻击防范与解决方案
SQL Server 2008/2005全解
SQL Server 2008/2005全解
SQL Server入门到精通
SQL Server入门到精通
· SQL Server入门到精通
· SQL Server 2008/2005..
· SOA 面向服务架构
· Apache技术专题
· C#技术开发指南
· 三层交换技术专题
· Apache技术专题
· C#技术开发指南
· Windows远程桌面应用
· 企业数据恢复指南
· Windows集群服务应用
· 路由器设置与口令恢复
· Linux 集群技术专题
· SOA 面向服务架构
· 了解统一威胁管理(UTM)..
· 解析35岁技术人的价值..