当前位置: 首页 > news >正文

所谓异常机制也就是指的语言平台支持异常这种错误处理模式的机制,比如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(user==null) {thrownewArgumentNullException("参数user为null"); }//调用Orm}

这里我们验证了入口参数,并尽早的抛出了异常,因为这里抛出的异常和不处理等db操作抛出异常,肯定是这里手动抛出的开销更小。这里有一个原则就是,如果这个参数会造成底层代码直接出错,那么就就近处理它,而不要放任其在底层造成系统异常的抛出。当然还有一个原则就是不要在这里判断业务逻辑,比如上面的例子就不要在这里验证User的属性的数值是不是合法之类的。

处理异常错误的例子

1:用异常验证用户输入

用户输入的合法性验证是属于业务逻辑的一部分,绝对不要用异常去处理,注意,是用户输入,所以这个经验仅限于表现层逻辑

典型的错误1:

try{inti=int.Parse(textBox1.Text); }catch(Exception ex) { alert(“不要输入非数字”); }

典型错误2:

voidValidateInput(inti) {if(i<0&&i>100) {thrownewException("输入数据范围错误"); } }

以上两种错误都是错误使用异常的典型,

2:将异常延迟到底层

这一点我们在正确的例子里提到过

典型错误3:

try{stringname=Request.QueryString["xx"]; List<User>userls=User.QueryUserByName(name); }catch(SqlException ex) { }

这个错误在于完全不验证用户输入而直接把数据的验证抛向数据库,等待数据库报错来判断用户输入的正确性,这个是非常致命的错误,很多注入漏洞都是由此产生的。

3:完全不用异常机制

产生这个错误肯定是一个非常脑残的决定造成的。不过很多时候某些不了解异常机制的人,由于对异常的性能开销的恐惧感,经常会做出这么脑残的决定。

典型错误4:

publicboolInsertUser(User user,refinterrcode) {if(user==null) { errcode=110;//参数为空错误的代码returnfalse; }//调用Orm
http://www.jsqmd.com/news/1131933/

相关文章:

  • 我警告了 329 天
  • Windows 10 21H2+ 系统 HP 打印机驱动 1603 报错:注册表 DisableUserInstalls 值修复指南
  • 反向传播 3 大常见问题:梯度消失、爆炸与 ReLU 死区排查
  • UGUI Mask 与 RectMask2D 性能对比:基于 2021.2.3f1 源码的 2 种裁剪方案实测
  • Unity Timeline 2022.3 精准暂停控制:3种代码方案对比与 Cinemachine 兼容性实测
  • 联想拯救者 2024 款散热实测:双烤 45 分钟 CPU 温度对比 3 款竞品
  • Linux /etc/fstab 配置详解:5个关键参数避免重启后文件系统只读
  • APT 包管理深度解析:从E: Unable to locate package看4种软件源失效场景
  • Linux Anaconda 环境迁移排错:解决3类路径错误与权限问题
  • TC78H660FTG与MK60DN512VLQ10的电机驱动系统设计
  • LSTM 与 GRU 门控机制对比:3 种变体参数量与梯度传播效率分析
  • E-R 模型向关系模式转换:8种场景实战与 MySQL 8.0 建表示例
  • Windows CMD 与 PowerShell 7 网络命令对比:5个场景性能与功能实测
  • HP 1005 打印机驱动 2 种安装方案对比:HPLIP 官方包 vs 发行版仓库
  • 呼和浩特定制网站还是模板建站?适配 GEO 优化的官网选型攻略
  • Spark Shell 与 PySpark 性能对比:5种常见算子在不同数据量下的执行耗时分析
  • 数据分析中的决策树算法是如何工作的?有哪些优缺点?
  • 数据库物理设计实战:MySQL 8.0 索引与存储引擎选择的 3 个性能基准
  • 蒙特卡洛强化学习 3 大核心实现:首次访问 vs 每次访问 vs 增量更新
  • Ubuntu 22.04 apt 源配置:3步诊断与修复 E: Unable to locate package
  • Linux LVM 根分区 (/dev/mapper) 100% 排查:3步定位MySQL日志等大文件
  • 【硬核脑洞】16位实模式最后的疯狂:我们能否在 640KB 常规内存里手搓一个 MD 模拟器?
  • QAM调制原理与Python仿真:从16-QAM到4096-QAM的误码率曲线绘制
  • Ubuntu 22.04/24.04 软件源配置:3大国内镜像站(阿里/清华/中科大)实测速度对比
  • 武汉昆仑星为企业AI可见度提升的四个变量:信源、内容矩阵、平台覆盖与复盘优化
  • YOLO26 改进 - 注意力机制 ACmix自注意力与卷积混合模型:轻量级设计融合双机制优势,实现高效特征提取与推理加速
  • Linux 进程通信 6 大机制对比:管道、消息队列、共享内存、信号量、信号、Socket
  • 个人系统的RULE和SOP是否有意义?
  • 如何用番茄小说下载器打造你的个人数字图书馆:Rust高性能工具的终极指南
  • HP LaserJet M226/M128 驱动安装 1603 错误:3 步定位与修复 HpTcpMon64.msi 故障