目录
一、异常的结构以及执行顺序
先上一段代码:a是多少?
int a = 0; try { a++; throw new Exception(); } catch (Exception ex) { try { a++; return; } catch (Exception ex1) { } finally { a++; } } finally { a++; }
先说一下三个块的运行关系(try、catch、finally)。
try块:尽可能地将比较容易出现异常的代码放在try块中,而且一个try块至少与一个catch块或者finally块匹配。try块中还是可能包含子try{}catch{}块。
catch块:1、是对抓取到的异常的一个响应,try块有可能关联0个或者多个catch块。 没有抓取到异常,跳过catch块,执行finally块(有的话)。可以抓取到异常,执行catch块中的代码。
2、捕捉到的类型必须为System.Exception类型或者派生类型。抛出异常,会自上而下进行匹配,所以将范围较小的异常类型放在上面。
如果没有匹配到异常类型,就会抛出一个为处理的一场类型。如果匹配到了异常类型,就执行内层所有的的finally块,catch块中的代码执行完毕后,再执行与这个catch块匹配的finally块。
finally块:肯定会执行,比如释放资源等操作。避免在finally中再次抛出异常。
二、System.Exception类
// 摘要: // 获取一个提供用户定义的其他异常信息的键/值对的集合。 // // 返回结果: // 一个对象,它实现 System.Collections.IDictionary 接口并包含用户定义的键/值对的集合。 默认值为空集合。 public virtual IDictionary Data { get; } // // 摘要: // 获取或设置指向此异常所关联帮助文件的链接。 // // 返回结果: // 统一资源名称 (URN) 或统一资源定位器 (URL)。 public virtual string HelpLink { get; set; } // // 摘要: // 获取或设置 HRESULT(一个分配给特定异常的编码数字值)。 // // 返回结果: // HRESULT 值。 public int HResult { get; protected set; } // // 摘要: // 获取导致当前异常的 System.Exception 实例。 // // 返回结果: // 一个 Exception 的实例,描述导致当前异常的错误。 InnerException 属性返回与传递给构造函数的值相同的值,或者,如果没有向构造函数提供内部异常值,则返回 // null 引用(Visual Basic 中为 Nothing)。 此属性为只读。 public Exception InnerException { get; } // // 摘要: // 获取描述当前异常的消息。 // // 返回结果: // 解释异常原因的错误消息或空字符串 ("")。 public virtual string Message { get; } // // 摘要: // 获取或设置导致错误的应用程序或对象的名称。 // // 返回结果: // 导致错误的应用程序或对象的名称。 // // 异常: // System.ArgumentException: // 该对象必须为运行时 System.Reflection 对象 public virtual string Source { get; set; } // // 摘要: // 获取调用堆栈上直接帧的字符串表示形式。 // // 返回结果: // 用于描述调用堆栈的直接帧的字符串。 public virtual string StackTrace { get; } // // 摘要: // 获取引发当前异常的方法。 // // 返回结果: // 引发当前异常的 System.Reflection.MethodBase。 public MethodBase TargetSite { get; }View Code
StackTrace:catch块可以读取这个属性获取堆栈跟踪,可以获取异常抛出前调用的方法。如果我们构造一个新的Exception类,StackTrace属性重置为null。访问该属性实际是执行了CLR代码。
如果一个异常抛出,CLR记录异常抛出的位置,catch块捕捉到异常,CLR会记录捕捉到异常的位置。我们在catch块内访问异常对象的StackTrace属性,实际还是会调用CLR代码,生成一个字符串,里面包含从异常位置到捕捉位置调用的所有方法。
后续。。。