【框架设计】异常
异常
概述:在程序编译中,异常是难免不遇到的。针对异常合适的处理,可以使代码健壮性更强,便于开发维护,有利于性能提升等特点。还有以下优点:1异常处理可以将资源文件代码放在一个指定的位置。如:try{}。。finally{}块中的代码 2异常处理可以将处理的代码放在一个集中位置。如:catch{}块。有时候导致代码的异常原因有:算术溢出,堆栈溢出,内存不足,参数越界,数组索引越界,资源已释放等。 3异常处理可以定位和修复代码中的bug。当代码发生故障时,公共语言运行库遍历线程的调用堆栈,查找能够处理的代码。
在程序编译中,异常是难免不遇到的。针对异常合适的处理,可以使代码健壮性更强,便于开发维护,有利于性能提升等特点。还有以下优点:
1异常处理可以将资源文件代码放在一个指定的位置。如:try{}。。finally{}块中的代码
2异常处理可以将处理的代码放在一个集中位置。如:catch{}块。有时候导致代码的异常原因有:算术溢出,堆栈溢出,内存不足,参数越界,数组索引越界,资源已释放等。
3异常处理可以定位和修复代码中的bug。当代码发生故障时,公共语言运行库遍历线程的调用堆栈,查找能够处理的代码。
本文主要涉及的内容:异常处理演变,异常处理机制,符合公共语言规范(CLS)的异常和不符合公共语言规范的异常,异常的准确定义,System.Exception类,FCL中预定义的异常类,抛出异常,定义自己的异常类,如何正确的使用异常类,性能考虑,未处理异常,异常堆栈跟踪,调试异常
异常处理演变
早期的开发人员,遇到异常问题,往往通过自己编写方法,查找故障原因.这些代码量加大,也不利于检查异常.后来微软NETFremawork2.0后,引入了异常处理机制.这样简便高效解决了异常问题,加大了开发速度.不过,那时候异常只是支持公共语言规范的异常.现在的版本对是否符合CLS的异常都支持.
异常处理机制
private void SomeMothod() {
try { 公共资源清理代码 }
catch (InvalidOperationException) { 相应的异常 throw; }
catch(IOException) { 相应的异常 throw; }
finally { 公共资源清理代码,不管是否异常抛出,总会执行 }
}
异常处理块有三部分组成,try{}..catch{}...finally{}
try放入资源清理代码(正常需要执行代码),catch{}里面对应的异常处理。finally{}里面也是资源清理代码。整个过程由上至下运行,里面可以包含多个catch{}块。一旦try{}发生异常,则执行catch代码。有CLR搜索捕获类型与抛出异常相匹配的catch块。进入堆栈顶部,自上往下检查,一旦有相应的异常将抛出异常。如果try执行后没有发现异常,则跳过catch执行finally部分。
符合公共语言规范(CLS)的异常和不符合公共语言规范的异常,
派生自Exception的异常对象成为符合公共语言规范的异常,而非Exception则为不符合CLS异常。例如:String,Int32等
异常的准确定义,
异常不等于错误,导致抛出异常的原因:
没有足够的堆栈空间,抛出StackOverflowExceptin异常
没有找到程序集定义的类型,抛出FileNotFoundException异常。
方法的IL没有通过验证,抛出verificationException异常。
系统没有足够的内存让JIT编译IL代码,抛出OutOfMemoryException异常。
System.Exception类,System.Exception类型的公共属性:
Message,异常抛出的原因,当异常无法处理时,该消息通常写入一个日志中。
Data,键值对集合的引用,代码抛出异常前,增加一条记录。偏于查询
Source,包含产生异常程序集名称
StackTrace,导致异常跑出的所以方法名称和签名,该属性对调试很有用。
TargetSite,抛出异常的方法。
HelpLink,指向文档的URL,帮助用户理解异常。一般远程发送其他编程人员。
InnerException,当前异常抛出时,系统正在处理,该属性表示前一个异常。
FCL中预定义的异常类
异常类定义在MSCorlib.dll程序集中。(公共语言运行库)System.Exception是所以异常的基础。但是不规范CLS异常除外。(非托管语言产生的异常)
抛出异常,
计划抛出派生自Exception的是什么类型异常?
基类异常是窄而深,以为其将许多错误看着一种错误不够具体。我们需要的是宽而浅的异常机制。尽可能具体到Exception的分支。我们自己编写的异常直接继承Exception
计划为异常类型的构造器传递什么样的字符串消息?
如果铺获出异常并处理异常,那么字符串消息就不见了。但是,假如异常没有处理,该消息通常会写入日志文件。
定义自己的异常类,注意引用IFormattable和IComparable
如何正确的使用异常类,验证方法参数和正确使用finally块。
异常处理一般try。。catch。。finally。但是很多编程语言提供了构造来简化编码,例如:
C#提供lock和using语句,可以使编译器自动产生try。。finally块。下面两个例子效果一样
例一:
private void SomeMothod()
{
FileStream fs = new FileStream(@"C:\Data.bin",FileMode.Open);
try
{
Response.Write(100/fs.ReadByte());
}
catch (InvalidOperationException)
{
}
finally
{
fs.Close();
}
}
例二:
private void SomeMothod()
{
using (FileStream fs = new FileStream(@"C:\Data.bin", FileMode.Open))
{
Response.Write(100 / fs.ReadByte());
}
}
两者效果一样,后者简洁很多
还有就是使用catch (Exception e) { }尽可能不要这样做,基类是窄而深的异常机制。
性能考虑,
使用异常处理,减少了很多代码。其利用垃圾回收机制。大大提高开发增加安全性。相对非托管代码性能有所提升。
未处理异常,
clr向上遍历整个堆栈查找与被抛出异常匹配的catch块,如果没有匹配,就出现未处理异常,当clr检测到进程中任意线程有未处理异常,都会终止进程。
异常堆栈跟踪
System.Exception提供StackTrace属性,访问其时,实际调用clr内部代码,构建新的异常类时,StackTrace为null。他的最大一个好处是处理堆栈跟踪和构成堆栈跟踪的栈帧。
调试异常
打开vs--》调试--》异常:
注意:该对话框支持不符合CLS异常类型
作者:白宁超,工学硕士,现工作于四川省计算机研究院,研究方向是自然语言处理和机器学习。曾参与国家自然基金项目和四川省科技支撑计划等多个省级项目。著有《自然语言处理理论与实战》一书。 自然语言处理与机器学习技术交流群号:436303759 。
出处:http://www.cnblogs.com/baiboy/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。