一起谈.NET技术,谈谈我处理异常的一般方法
2011-09-01 23:47
295 查看
我们在编写程序的时候会遇到各种各样的意外情况,如除数为0,数组越界,非法转型,栈溢出等等。因而我们需要有一种机制来处理这些情况,异常处理就是其中的一种机制。当然,还有其他的机制,在MFC中,由于标准的不统一,就存在着各种错误报告方法,如有通过函数返回特殊值的方式,有通过执行某一语句后查询特殊语句获取错误的码的方式,等等。
在C#中,只有一种报告方式,即异常。这样可以让开发人员从大量的文档中解脱出来,不必为一些非逻辑的问题而花费大量时间。
C#中的异常不同于C++,所有的异常类型都是继承自System.Exception的,因此我们定义自己的异常类型时,都要继承自System.Exception或者该类的子类。
常见的异常语句如下:
如果Login()会抛出一个InvalidOperationException,logout()会抛出一个InvalidOperationException,我们可能不得不进一步分析这些异常,然后才能对这些操作作出适当的应对措施。
对于一个规模不大的类,我习惯于定义包含一个枚举类型的类的异常。例如,上面这个例子,我会定义UserOperationException, UserManagerOperationException, ArticleOperationExcetpion,ArticleOperation这些异常,以UserOperationException为例子
使用这样的继承方式,我们就可以更加灵活的来进行异常处理。
现在讨论一下如何进行异常捕获。
我认为在写程序的时候,可以首先考虑程序的逻辑问题,非逻辑问题,即异常捕获可以不进行处理。继续以用户登录为例子:
当然了,这样的编码方式还是要在编码过程中来关注这些异常。在我所了解的范围内,微软提供了一个开源的企业库Microsoft Enterprise Library(http://entlib.codeplex.com/),该库提供了一个ExceptionHandling Application Block,我们可以用更加灵活方式来处理这些异常,比如全部在配置文件里面做。
当然,还有其他的方式来解决异常处理的问题,比如AOP技术。最近一直对AOP比较感兴趣,但并没有相关的实践,因此也没有什么经验可谈。
如果您完整的看完了我的文章,希望您可以根据您的经验指出文章中存在的问题。这篇文章只是一个我的经验总结。
在C#中,只有一种报告方式,即异常。这样可以让开发人员从大量的文档中解脱出来,不必为一些非逻辑的问题而花费大量时间。
C#中的异常不同于C++,所有的异常类型都是继承自System.Exception的,因此我们定义自己的异常类型时,都要继承自System.Exception或者该类的子类。
常见的异常语句如下:
http://www.cnblogs.com/aoaoblogs/archive/2009/12/08/1619827.html)。我认为,对于在处理问题主要逻辑范围以内的问题,不要使用异常。主要逻辑范围,指的是在完成一件任务的主要路径。 比如我现在要进行一个查询工作,查询一下用户在不在,如果该用户在,那么我应该返回true,不在则应该返回false,我在用这个方法的时候,我对他的直接期望是得到一个返回值。然而,在查询过程中会发生一些其他错误,如数据库无法连接,数据库并发连接数过大。这些问题,就应当是异常处理所要面对的问题。又比如我希望上传一个文件,我用的时候就直接调用该方法,该语句在设计之初,就应当是直接能上传的。 还有就是什么样的问题需要抛出。 我认为,在设计过程中,在一些不可恢复的情况下,才有抛出异常的必要。应当在文档中列出较少的可能抛出的异常。我们继续以查询用户为例子,在查询数据库的过程中,我们发现数据库无法连接,如果该查询方法对时间要求不是很严格,我们应当使用一些策略来使得该方法能完成,如再次尝试连接。在尝试连接一定次数之后,我们才需要引发异常。 还有我认为,我们在设计方法的时候,要捕获所有的方法内语句产生的异常,并将异常包装后抛出,而不是直接抛出。并且抛出的异常最好是与逻辑相关的。继续用查询用户做例子,数据库链接出错、网络不可用之类的问题,我认为为了方便开发者使用该类(其实有时候开发者往往就是自己),我们应当将这些异常都放到一个异常类型中,如EnvironmentException,然后定义一个枚举,将该枚举作为EnvironmentException的属性。我们在捕获异常的时候,只要捕获该类型的异常就好了,如果希望了解异常细节,我们则可以使用InnerException获取引起该异常的异常。 下面讨论怎样定义异常的问题。 在.net中有许多内置的异常,如InvalidOperationException、InvalidCastException等,这些异常都继承自System.SystemException。我在定义异常的时候,通常直接继承自System.Exception。我个人认为,一个方法不应该抛出太复杂的异常,而使得开发者困惑。我抛出一个异常,只是把一个方法执行过程中所存在的问题抛出了。我想,得到一个与这个方法逻辑相关的异常、看到名字就大概知道哪里出错的异常,总比一个InvalidCastException这样的异常好多了。 比如以下是一段语句。 try{ var user=userManager.GetUser(id); user.Login(); user.Logout(); var article=articleManager.getArticle(articleId); article.user=user; article.save(); }catch{ … }
如果Login()会抛出一个InvalidOperationException,logout()会抛出一个InvalidOperationException,我们可能不得不进一步分析这些异常,然后才能对这些操作作出适当的应对措施。
对于一个规模不大的类,我习惯于定义包含一个枚举类型的类的异常。例如,上面这个例子,我会定义UserOperationException, UserManagerOperationException, ArticleOperationExcetpion,ArticleOperation这些异常,以UserOperationException为例子
public enum LoginOperationException:UserOperationException{ public LoginOperationException(string message,ExceptioninnerException) :base(message,innerException,UserOperationStatus.Login) { .. } }
使用这样的继承方式,我们就可以更加灵活的来进行异常处理。
现在讨论一下如何进行异常捕获。
我认为在写程序的时候,可以首先考虑程序的逻辑问题,非逻辑问题,即异常捕获可以不进行处理。继续以用户登录为例子:
public function void Login(string username,string password){ try{ //_UserManager是类的一个私有字段 var user=_UserManager.GetUserByName(username); if(user.password==password) { user.Login(); Console.WriteLine(“Success”); user.Logout(); Console.WriteLine(“Logout Success”); }else{ Console.WriteLine(“Invalid password”); } }catch(UserManagerOperationException){ Console.WriteLine(“User doesn’t exist”); }catch(UserLoginOperationException ex){ switch(ex.LoginStatus){ case LoginStatus.DB: Console.WriteLine(“DB errors”); break; case LoginStatus.Network: Console.WriteLine(“Network errors”); break; }catch(UserOperationExceptionex){ Console.WriteLine(“Other exception {0}”,ex); } }
当然了,这样的编码方式还是要在编码过程中来关注这些异常。在我所了解的范围内,微软提供了一个开源的企业库Microsoft Enterprise Library(http://entlib.codeplex.com/),该库提供了一个ExceptionHandling Application Block,我们可以用更加灵活方式来处理这些异常,比如全部在配置文件里面做。
当然,还有其他的方式来解决异常处理的问题,比如AOP技术。最近一直对AOP比较感兴趣,但并没有相关的实践,因此也没有什么经验可谈。
如果您完整的看完了我的文章,希望您可以根据您的经验指出文章中存在的问题。这篇文章只是一个我的经验总结。
相关文章推荐
- 谈谈我处理异常的一般方法
- 一起谈.NET技术,.NET中锁6大处理方法 悲观乐观自己掌握
- 谈谈我处理异常的一般方法
- 一起谈.NET技术,.NET 4.0里异常处理的新机制
- 一起谈.NET技术,.Net创建Excel文件(插入数据、修改格式、生成图表)的方法
- 一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(九)粒子系统
- 一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(二)纸娃娃系统
- 一起谈.NET技术,从扩展方法到流畅的程序体验(一)
- 一起谈.NET技术,改善代码设计 —— 处理概括关系(Dealing with Generalization)
- 一起谈.NET技术,如何将XML与OBJECT进行相互转换(泛型以及通用方法)
- 一起谈.NET技术,数组排序方法的性能比较(中):Array.Sort<T> 实现分析
- 【.net项目中。。】.net一般处理程序使用方法
- 一起谈.NET技术,在ASP.NET 2.0中数据绑定的实现方法
- 一起谈.NET技术,数组排序方法的性能比较(3):LINQ排序实现分析
- 一起谈.NET技术,SilverLight调用WebService的方法
- Delphi 中自定义异常及异常处理的一般方法
- 一起谈.NET技术,关于c#静态方法和实例方法的辨析和应用
- 一起谈.NET技术,.NET动态调用DLL的方法
- 一起谈.NET技术,谈谈C# 4.0新特性“缺省参数”的实现
- CASE函数 sql server——分组查询(方法和思想) ref和out 一般处理程序结合反射技术统一执行客户端请求 遍历查询结果集,update数据 HBuilder设置APP状态栏