所谓异常机制也就是指的语言平台支持异常这种错误处理模式的机制,比如c#里的Exception对象,try{}catch{}finally{}结构,throw抛出异常的语句,等等,均为c#语言里对异常机
异常对象异常对象是异常机制中用来描述异常记录错误信息可以说是错误发生是的快照就跟你开快车闯红灯被天眼拍到的照片差不多。抛出异常所谓抛出异常就是异常机制中通知调用的方法本方法出错了的手段。而抛出异常也是很多人诟病异常对性能影响的地方因为系统性能的开销都是由抛出异常所引起的。但是抛出异常也无法避免因为这是系统本身的特点你不抛出异常系统自己也会抛出一旦系统抛出了异常对象你怎么来避免这个性能的开销没辙比如方法A调用了方法B方法B访问数据库出错了那么B就会抛出异常而A就需要catch这个异常来处理。抛出异常有两种形式一种是系统抛出的异常一种是我们自己认为在处理一段逻辑的时候当逻辑错误就可以通过抛出一个异常对象来通知调用这个方法的方法这里出错了。系统抛出异常系统抛出的异常对编程人员来说是透明的也就是我们不需要关心系统是如何得知出错了的系统类库一旦出错就会将异常对象抛给我们调用它的方法因为系统本身并不知道要如何处理这个错误。用户抛出异常用户抛出异常通常在自己写类库定义一套API给别人使用的时候用到这个时候我们并不知道要如何处理这些逻辑错误所以就需要交给知道如何处理逻辑错误的方法去处理。在C#里通过定义了throw关键字来抛出异常对象这里除了抛出新创建的异常对象也可以通过将已经catch到的异常重新抛出。如果不知道如何处理这个异常重新抛出异常是很好的习惯因为既然已经抛出了异常那么性能已经损失了所以也不在乎多这么一丁点来更好的挽回错误的结果。处理异常所有的异常必须得到妥善的处理也就是说你必须处理所有的异常。因为系统出错就抛异常所以这个是c#骨子里的东西无法避免所以系统里到处都会充斥着try{}catch{}。但是try{}catch{}本身并不会影响系统的性能所以在没有异常发生的时候try{}catch{}是不会让你系统变慢的而一旦发生系统异常你不处理系统就崩溃掉了你到底是愿意系统慢一点点然后处理掉这个错误呢还是愿意系统崩溃掉呢对于处理异常这一点其实我觉得java那种比较严格的要求严格声明并处理所有异常的方式比较好能够强制让你重视起异常这回事来免得系统崩溃掉才想起自己没处理这个异常。如何处理如何正确的处理异常这是个很多c#程序员都没最终搞明白的话题很多人所了解的也无非就是不要用异常处理当业务逻辑但是何谓用异常来处理逻辑就不得而知了。这里我来详细说明一下什么地方要用异常什么地方不要用。首先有一个前提异常机制是一个由底向上的冒泡的过程所以正常的逻辑是异常由底层抛出由高层来处理。处理异常正确的例子要编写健壮的引用程序首先要保证必须处理所有的系统异常也就是调用.NET类库的方法的时候这个方法可能抛出的异常例我们可以看到GetResponse方法会抛出两个异常 InvalidOperationException和WebException。那么我们就需要将调用的代码所在的catch单独处理这两个异常如果你在这个方法中不知道应该如何处理这个异常比如这个方法不上不下和表现层离了好几层而又需要在表现层通知用户或者由上层业务来决定是通知用户还是悄悄的进村又或者是悄悄的重新尝试一次那么自己不能决定的事情就要抛给上层去处理。有人可能会说.NET可以统一处理异常的不过我不推荐那种大而全的处理方式不够细致很多时候会被奇怪的错误搞得你很追查错误的本源。且比如说遇到网络问题重试就没法处理。异常必须就近处理这样才能方便追查而且注意那个“xxx方法出错了”那个地方很重要这个描述可以让你在系统排错的时候少走很多弯路尽量写详细点。如果你的代码是给别的程序员使用而不是和最终用户直接交互那么除了处理所有系统抛出的异常以外还需要用异常来验证过滤入口参数。比如假设你要给其他程序员提供一个将用户对象插入数据库的方法publicvoidInsertUser(User user) {if(usernull) {thrownewArgumentNullException(参数user为null); }//调用Orm}这里我们验证了入口参数并尽早的抛出了异常因为这里抛出的异常和不处理等db操作抛出异常肯定是这里手动抛出的开销更小。这里有一个原则就是如果这个参数会造成底层代码直接出错那么就就近处理它而不要放任其在底层造成系统异常的抛出。当然还有一个原则就是不要在这里判断业务逻辑比如上面的例子就不要在这里验证User的属性的数值是不是合法之类的。处理异常错误的例子1用异常验证用户输入用户输入的合法性验证是属于业务逻辑的一部分绝对不要用异常去处理注意是用户输入所以这个经验仅限于表现层逻辑典型的错误1try{intiint.Parse(textBox1.Text); }catch(Exception ex) { alert(“不要输入非数字”); }典型错误2voidValidateInput(inti) {if(i0i100) {thrownewException(输入数据范围错误); } }以上两种错误都是错误使用异常的典型2将异常延迟到底层这一点我们在正确的例子里提到过典型错误3try{stringnameRequest.QueryString[xx]; ListUseruserlsUser.QueryUserByName(name); }catch(SqlException ex) { }这个错误在于完全不验证用户输入而直接把数据的验证抛向数据库等待数据库报错来判断用户输入的正确性这个是非常致命的错误很多注入漏洞都是由此产生的。3完全不用异常机制产生这个错误肯定是一个非常脑残的决定造成的。不过很多时候某些不了解异常机制的人由于对异常的性能开销的恐惧感经常会做出这么脑残的决定。典型错误4publicboolInsertUser(User user,refinterrcode) {if(usernull) { errcode110;//参数为空错误的代码returnfalse; }//调用Orm