惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
Y
Y Combinator Blog
aimingoo的专栏
aimingoo的专栏
B
Blog
小众软件
小众软件
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
L
LangChain Blog
WordPress大学
WordPress大学
罗磊的独立博客
GbyAI
GbyAI
S
SegmentFault 最新的问题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
IT之家
IT之家
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
雷峰网
雷峰网
美团技术团队
F
Fortinet All Blogs
Hugging Face - Blog
Hugging Face - Blog
The GitHub Blog
The GitHub Blog

博客园 - 兵

CryptoAPI与.NET数字签名类的交互问题 Firefox中Iframe的blur与focus事件问题 .NET中几种基本的线程同步方法 为什么说WinForm的控件只能在主线程中创建和调用 C#与Native C++互相访问 PHP5中的引用 Windows版的PDO太衰了 Framework里某些类型成员方法的一点疑惑 发现一个FireFox的问题 C#中COM操作(二)---接口查询 C#中COM操作(一)---实例化 非弹出式的模态对话框的背景遮罩 DOTNET事件拾遗 CSS开发辅助工具:Internet Explorer Developer Toolbar 另外一种高效地判断奇数和偶数的方法 如何利用客户端缓存对网站进行优化? 一个多表查询引出的问题(2) 类的成员初始化顺序 一个多表查询引出的问题(1)
C#异常处理的方式
· 2012-06-26 · via 博客园 - 兵

C#异常处理的方式

c#中所有可以被抛出的异常都是直接或间接继承自System.Exception

支持的捕获异常的语句块如下:

try … catch

try … catch … finally

try… finally

c#代码块中生成异常堆栈信息的时机不是在throw语句执行的地方,而是在第一次捕获的地方

以上三种方式中 try ... finally一定不会影响堆栈信息

可能会影响的地方主要集中在catch块中

catch子句声明方式又有以下几种

catch{}

catch(Exception){}

catch(Exception ex){}

这三种写法从捕获异常的能力上来说基本上是等效

第三种方式只是让编写代码的人可以使用异常参数,如果不使用异常参数的话可以用前面两种,第二种只是更加明确的指出了捕获的是Exception或者是从Exception继承的异常

catch块内可以再次抛出异常,抛出时可以支持下面几种方式

throw;

throw ex; // ex来自于catch(Exception ex)

throw new SomeException();

后面两种情况是一样的, stack trace认为你catch到的异常已经被处理了,只不过处理过程中又抛出新的异常,这时候stack trace就把throw 后的那个异常实例当作错误根源了。之前的堆栈信息全部会清除掉

第一种方式网上和MSDN上都说可以保留堆栈信息。经测试发现不全是如此:

Debug版本下,生成的代码在执行没有任何优化,直接使用throw;这种方式的确是能保留堆栈信息。这个时候的堆栈信息就好像是在try块内部异常产生的地方就记录好了一样。

Release下,输出的信息中只包含了从捕获位置开始向上的堆栈信息。即从异常源发生位置到第一次catch块捕获发生之间的堆栈信息都不存在了

总结如下:

以前的异常信息中有出错的点很容易就找到了,那是因为正巧异常源与第一次捕获的地方很接近

否则的话越是在调用的最上层捕获到异常,越不容易找到异常源在什么位置(这里都是在Release条件下)

Release版本下,异常越早捕获,越能精确定位出错位置,越晚捕获,从堆栈中获得的获得的有效信息也越少,即使是用了throw;这样的方式也一样

严格禁止 下面这种写法:

try{

         // do

}

catch(Exception ex)

{

throw ex;

}

如有必要需改用 throw; 或者 throw new SomeException(msg, ex); 这样的形式

如果是捕获了异常不想再次抛出(一般用在捕获到的异常在预期范围内,已经有相应的处理方式了),最好是能记录日志,表示发生过异常

附上一个测试:

Release 使用throw;

Release 使用throw ex;

 

Release下更极端的例子去掉了除最外层外所有的try…catch

 

Debug 使用throw;

 

Debug 使用throw ex;