C# 异常处理[转]
2012-03-07 15:36
204 查看
异常处理结构
开发软件一定要有足够的风险意识,认识到商业软件在各种复杂的情况下运行,必然会出现各种各样的风险和错误,这些风险和错误需要进行处理。无视风险和错误,假设一切都很和谐是很危险的思想。主动处理错误
程序开发中可以主动处理错误和被动处理错误,主动处理错误就是进行写代码进行功能执行前的检查,最常见也是最有效的手段就是在方法体开头处检查方法参数是否正确。主动检查程序运行速度快,而且系统更稳定,而且将风险消灭在萌芽之中,避免后期的错误大爆发,因此是优先采用的风险处理方式。[袁永福版权所有]例如下面的代码就是主动处理错误。
public int Div( int a , int b ) { // 检查参数,若b为0,则必然会爆被0除的错误,提前处理错误。 if (b == 0) { return 0; } return a / b; } |
被动异常处理
主动处理错误的方式很可能会有遗漏,C#中可以采用异常捕获机制来被动的处理错误。在说明异常前首先得讲讲程序的调用堆栈的概念。其实基本上所有的编程语言都有调用堆栈的功能。例如在程序运行时,方法F1调用了方法F2,F2在某个瞬时又调用了方法F3,而方法F3在某个时刻调用了方法F4。则此时刻存在“F1
| F2 | F3 | F4”的调用堆栈。如下图所示,此时程序的代码呈现为一种洋葱一样的按照方法分层的结构,越靠里层就越是底层代码。
C#中的异常就是程序模块发生错误的信息,抛出异常就是程序通知系统程序发生错误了,这种异常是全局性,从抛出点开始,沿着调用堆栈,一层层的向上推动,越往上,影响面越大,若调用堆栈上某层代码能主动捕获并处理这个异常,该异常就消失掉了,系统就能正常运行,若一直没有代码能主动捕获异常,则该异常就会一直捅到了.NET框架层面。
例如在F1、F2、F3、F4构成的调用堆栈中个,如果方法F4内部主动抛出了一个异常,该异常首先抛给了方法F3,若F3不处理异常则该异常又抛给了F2,若F2还是没有处理则继续抛给了F1,若F1没有处理则直接抛给了.NET框架系统本身了。
这有点像上访,村里的农民觉得不满到找村长上访,村长不处理接着到县里上访,县里不处理则到省里上访,省里不处理则最后跑到中央上访,中央总是以简单粗暴的方式处理任何上访的。
不过凡事惊动中央是不好的,.NET框架就是.NET应用程序的中央,.NET框架本身处理没有被程序处理的异常会弹出如下的程序错误对话框
对于该对话框,若点击“继续”按钮则程序或许还能接着运行,但可能出于一种不稳定的状态;点击“退出”按钮则立即无条件的退出程序,这可能导致数据未保存。[袁永福版权所有]
一旦显示出系统级错误对话框,则该程序的稳定性可靠性是非常的差,应当尽量避免这种情况。这就需要在调用堆栈中的某些合适层面的方法中添加异常处理来应付底层方法抛出的异常。
在C#中使用“throw”关键字抛出以上,以下代码就演示了抛出异常。
public int F1() { throw new Exception("这里发生异常了"); } |
注意方法F1定义为需要返回一个整数数值,若方法体中没有return语句编译不通过的,但使用throw语句时可以压住这个规定。
在C#中使用“try{ }catch{ }finally{ }”结构来处理异常,以下代码就演示了如何处理异常
public void HandleException(int a, int b) { try { // 进入能捕获异常的状态 F1(); } catch (Exception ext) { // 若发生异常,在此捕获异常,执行这段代码 System.Windows.Forms.MessageBox.Show(ext.Message); } finally { // 不管有没有发生异常,本段代码都运行 Console.WriteLine("完成了处理"); } } |
} catch { }”或者“try{ } finally{ }”。[袁永福版权所有]
对于“try{ } catch{ }”结构,程序会捕获异常并处理掉,使得异常不再上访。
对于“try{ } finally{ }”结构,程序会感知异常,做一些处理,但不会捕获异常,异常仍然会接着上访。
使用异常处理,就能让底层方法抛出的异常被及时的处理掉而不至于一路捅到.NET框架而成为系统级的错误。因此开发程序时必须加上合适的异常处理。
由于异常是被动的处理错误,而且执行过程消耗了不少资源,因此主动防御错误永远比被动处理错误要好。在实践中可以考虑将两者都用上,做好双保险,这样程序才能可靠稳定。[袁永福版权所有]
using 语法结构
在C#中,关键字using出了可以引用命名空间外,还可以使用using结构来实现一定的异常处理。语法结构为“using( ) { }”。例如以下代码就演示了using结构。using (System.IO.FileStream stream = new System.IO.FileStream("c:\\a.txt", System.IO.FileMode.Create)) { stream.WriteByte((byte)2); } |
文件流是一种很重要的资源,打开后必须被关闭,否则就会资源泄露,在上面的代码中应该补上代码“stream.Close( )”来关闭文件流。但实际上面的代码是安全的,不会出现资源泄露问题,这是因为采用了using语法结构。
上述代码其功能等价于以下代码
System.IO.FileStream stream = new System.IO.FileStream("c:\\a.txt", System.IO.FileMode.Create); try { stream.WriteByte((byte)2); } finally { ( (System.IDisposable)stream).Dispose(); } |
从这里可以看出using语法结构具有一定的异常处理功能,它没有捕获异常,但能感知异常,并进行了一些处理来减少异常带来的负面影响。
C#中的using语法结构是针对System.IDisposable接口的,System.Idisposable接口只声明了一个成员“void Dispose( )”,用于释放对象所占有的重要资源。任何实现了System.IDisposable接口的对象都能被用上using结构,比如文件流、数据库连接、网络连接等等。[袁永福版权所有]
相关文章推荐
- 在C#中利用Keep-Alive处理Socket网络异常断开的方法
- C# 网络连接中异常断线的处理:ReceiveTimeout, SendTimeout 及 KeepAliveValues(设置心跳)
- .NET(C#):Emit创建异常处理的方法
- Head First C# 中文版 第10章 异常处理 page446
- Head First C# 中文版 第10章 异常处理 page448
- [C#] C# 知识回顾 - 学会处理异常
- C#_WinForm捕获未处理的异常
- Head First C# 中文版 第10章 异常处理 page466
- C# 阻塞方式Socket接受异常处理(不定期更新)
- c#中构建异常处理
- Head First C# 中文版 第10章 异常处理 page474
- C#的异常处理
- (C#基础)异常处理二三事
- C++ /python/java /C# 自定义异常处理
- 第九 讲 : C# 的异常处理- 【天轰穿.Net4趣味编程系列视频教程-vs2010轻松学习C#】
- C#OOP之十 异常机制及其处理
- C#.NET--如何处理程序的未捕获异常
- 在C#中利用Keep-Alive处理Socket网络异常断开的方法
- C# 异常处理-finally 和 return
- c#中构建异常处理