第三节:System.Exception类型

CLR允许异常抛出任何类型的实例,从Int32到String都可以。但是,Microsoft决定不强迫所有编程语言都抛出和捕捉任何类型的异常。因此,他们定义了System.Exception类型,并规定所有CLS相容的编程语言都必须能抛出和捕捉该类型的异常。派生自System.Exception的异常类型被认为是CLS相容的。C#和其他许多编程语言的编译器都只允许代码抛出CLS相容的异常。

System.Exception是一个非常简单的类型,它包含了一些属性。但是,一般不要写任何代码以任何方式查询或访问这些属性,相反,当应用程序由于一个未处理的异常而终止时,可以在调试器中查看这些属性,或者在Window应用程序事件日志或崩溃转储中查看。

这里有必要讲一下System.Exception异常提供的只读属性StackTrace.catch块可读取该属性来获取一个堆栈跟踪,它描述了异常发生前调用的方法。为了检查异常原因并修改代码,堆栈跟踪非常有用。访问该属性时,实际要调用CLR中的代码;该属性并不是简单返回一个字符串。构造一个Exception派生类的一个新对象时,StackTrace属性被初始化为null.如果此时读取该属性,得到的不是堆栈跟踪,而是一个null。

一个异常抛出时,CLR会在内部记录throw指令的位置(抛出位置)。一个catch块捕捉到该异常时,CLR又会记录异常的捕捉位置。在catch块内访问被抛出的异常对象的StackTrace属性,负责实现该属性的代码会调用CLR内部的代码,后者创建一个字符来指出从异常抛出位置到异常捕捉位置的所有方法。

以下代码抛出和它捕捉的一样的异常对象,导致CLR重置该异常的起点:

Private  void  SomeMethod()

{

try{}

catch(Exception e)

{throw  e;}//CLR认为这是异常的起始点。

}

相反,如果仅仅使用throw关键词本身(删除后面的e)来重新抛出一个异常对象,CLR就不会重置堆栈的起点。以下代码重新抛出它捕捉到的异常,但不会导致CLR重置起点。

Private  void  SomeMethod()

{

try{}

catch(Exception e)

{throw ;}//不影响CLR对异常起点的认识

}

实际上,上述两段代码的唯一区别就是CLR对异常的起始抛出位置的认知。令人遗憾的是,抛出或重新抛出一个异常,Window会重置堆栈起点。因此,如果一个异常成为一个未处理的异常,那么向Windows Error Reporting报告的堆栈位置就是最后一次抛出或重新抛出的位置。之所以令人遗憾,是因为假如应用程序在字段哪里失败会使调试工作变的异常困难。有一些开发人员无法忍受这一点,于是选择以一种不同的方式来实现代码,确保堆栈跟踪能真正返回一个异常的原始抛出位置:

Private   void  SomeMethod()

{

Boolean  trySucceeds=false;

Try

{

trySucceeds=true;

}

Finally

{

If(!trySucceeds)

}

}

在StackTrace属性返回的字符串中,不包含调用栈中比接受异常对象的那个catch块高的任何方法。要获得从线程起始处到异常程序之间的完整堆栈跟踪,需要使用System.Diagnostics.StackTrace对象。该类型定义了一些属性和方法,允许开发人员程序化的处理堆栈跟踪以及构造堆栈跟踪的栈帧。

可能有几个不同的构造器来构造一个StackTrace对象。一些构造器构造从线程起始处到StackTrace对象的构造位置的栈帧。另一些构造器使用作为参数传递的一个Exception派生对象来初始化栈帧。

如果CLR能找到你的程序集的调试符号(存储在pdb中),那么在System.Exception的StackTrace属性或者System.Diagnostics.StackTrace的ToString方法返回的字符串中,将包含源代码文件路径和代码行号,这些信息对于调试时非常有用的。

获得一个堆栈跟踪后,可能发现在实际调用栈中有的一些方法没有出现在堆栈跟踪字符串中。这是由于两种原因造成的。首先,调用栈其实是线程返回位置的一个记录。

其次,JIT编译器可能内联一些方法,从而避免了调用一个独立的方法并从中返回的开销。许多编译器都使用了/Debug命令行开关。使用这个开关,编译器会在生成的程序集中嵌入信息,告诉JIT编译器不要内链程序集的任何方法,确保调试人员获得一个更完整、更有意义的堆栈跟踪。

时间: 2024-10-14 06:19:07

第三节:System.Exception类型的相关文章

“System.Exception”类型的异常在 NHibernate.dll 中发生,但未在用户代码中进行处理

“System.Exception”类型的异常在 NHibernate.dll 中发生,但未在用户代码中进行处理 其他信息: OCIEnvCreate 失败,返回代码为 -1,但错误消息文本不可用. 如有适用于此异常的处理程序,该程序便可安全地继续运行.

编写高质量代码改善C#程序的157个建议——建议68:从System.Exception或其他常见的基本异常中派生异常

建议68:从System.Exception或其他常见的基本异常中派生异常 微软建议:从System.Exception或其他常见基本异常之一派生异常.在Visual Studio中输入Exception,然后按快捷键Tab,VS会自动创建一个自定义异常类: [Serializable] public class MyException : Exception { // // For guidelines regarding the creation of new exception types

“System.InvalidOperationException”类型的未经处理的异常在 ESRI.ArcGIS.AxControls.dll 中发生

问题描述: 新手们进行ArcGIS ArcObject开发时经常会遇到各种十分古怪的问题,比如下面的这个问题: “System.InvalidOperationException”类型的未经处理的异常在 ESRI.ArcGIS.AxControls.dll 中发生 其他信息: ArcGIS version not specified. You must call RuntimeManager.Bind before creating any ArcGIS components. 此时虽然程序能正

“System.FormatException”类型的未经处理的异常在 System.IdentityModel.dll 中发生 其他信息: 十六进制字符串格式无效。

如果你的 WebService 客户端证书配置都没问题,唯独调用接口会出现这个错误 "System.FormatException"类型的未经处理的异常在 System.IdentityModel.dll 中发生 其他信息: 十六进制字符串格式无效. 解决办法: 打开你的证书列表,找到证书指纹: 接下来是重点,复制的时候,切记不要用全选,像这样: 要用鼠标仔细的从第一个"可见"字符选起,到"可见"字符结束,像这样: 请仔细对比以上两张图的差别,不

“System.BadImageFormatException”类型的未经处理的异常在 PurchaseDevices.Access.dll 中发生 其他信息: 未能加载文件或程序集“System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139”或它的某一个依赖项。试图加载格式不正确

引用sqlite的程序集时,有时会报如下异常: "System.BadImageFormatException"类型的未经处理的异常在 PurchaseDevices.Access.dll 中发生 其他信息: 未能加载文件或程序集"System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"或它的某一个依赖项.试图加载格式不正确的程序. 解决方案:在配置

System.AccessViolationException”类型的未经处理的异常在 System.Data.dll 中发生

错误背景: 操作系统:编程环境:VS2013:  语言:VB.net:  数据库:SQLserver2008 做数据库连接时,发生的错误: 错误提示为: 说明:用VB.net连接SQLServer数据库 第一种情况: 连接字符串为"Server=(Local);Database=charge_sys;UserID = sa;Password=123456"时,连接没问题: 第二种情况: 当把" Server=(Local)"换为 " Server=192.

System.AccessViolationException”类型的未经处理的异常在 System.Data.dll 中发生。其它信息:尝试读取或写入受保护的内存。这通常指示其它内存已损坏。

错误背景: 操作系统:编程环境:VS2013.  语言:VB.net:  数据库:SQLserver2008 做数据库连接时.发生的错误: 错误提示为: 说明:用VB.net连接SQLServer数据库 第一种情况: 连接字符串为"Server=(Local);Database=charge_sys;UserID = sa;Password=123456"时,连接没问题: 另外一种情况: 当把" Server=(Local)"换为 " Server=192

是否存在不继承自System.Object类型的类

分析问题 可能读者的固有思维认为.NET中所有的类型都必须继承自System.Object,这样的认识过于绝对,且不完全正确.在.NET中,.NET设计小组为中间语言的编译器ILasm.exe添加了noautoinherit开关,当这个开关被打开时,编译器将不会默认年地把类型认为继承自System.Object. 首先介绍一下中间语言的编译工具:ILasm.exe.这是.NET Framework提供的一个编译工具,它的作用是把中间语言(MSIL)编译成可执行的PE文件.该工具非常有用,它不仅使

“System.NullReferenceException”类型的异常在 App_Web_j2s3gau3.dll 中发生,但未在用户代码中进行处理的Bug解决方案

这个异常报错的原因也许在不同的项目中,也有很多种原因导致出错.在这里我针对我的项目,看了报错的提示,找了大半天.终于找到了..唉..虽然简单,但还是写写. 我的项目里实现了URL的重写,URL重写类里面做了一个“网站访问日志”的功能,该功能只不过是记录来网站的URL,并保存数据库中.在这里我用到了,缓存(HttpRuntime.Cache),在整个应用程序中都可以访问该值.之前的是 Microsoft .NET Framework 3.5,现在我 升到Microsoft .NET Framewo