当应用程序捕获一个异常时,代表着我们为应用程序引入了一个“具有破坏性的事件“,异常可能会对系统资源或者应用程序的状态有破坏,我们应该避免这种情况发生。

Dave Abrahams对于异常,定义了3种情况:1. 基本保证;2、强保证;3、无异常抛出。

基本保证,确保在应用程序抛出异常后,没有任何资源泄漏,并且所有对象都处于有效状态;强保证,在基本保证的基础上,又添加了“如果有一场抛出,程序状态保留不变”的条件;“无异常抛出”确保一个操作在任何情况下都不会失败,也就是说一个方法永远不会将异常抛出。通常情况下,强异常机制在“从异常中恢复”和“简化异常处理”之间提供了最好的平衡。

在C#中,由于.NET提供了垃圾回收机制,因此它可以默认提供“基本保证”,因此只有以下情况下才会需要手动释放:在拥有一个实现了IDisposable接口的资源时,跑出了一个异常。

“强异常保证”确保如果操作因为异常而中断,那么程序状态保持不变,操作或者完成或者不改变程序状态,没有中间态。

我们可以通过以下步骤来实现强异常保证。

1. 对将要修改的数据做“防御性的复制”。

2. 对这些数据的“防御性复制”进行修改,这些中间操作可能会引发异常。

3. 将临时的副本和原对象进行交换,交换操作不可能抛出任何异常。

我们可以看以下的代码。

代码

1 public void PhysicalMove( string title, decimal newPay )
2 {
3 // Payroll data is a struct:
4 // ctor will throw an exception if fields aren't valid.
5   PayrollData d = new PayrollData( title, newPay,
6 this.payrollData.DateOfHire );
7
8 // if d was constructed properly, swap:
9   this.payrollData = d;
10 }

下面来讨论“无异常抛出保证”,即方法一致运行,不会有异常抛出。在大部分情况下,这样做是不现实的,但是在以下情况下,还是需要使用“无异常抛出保证”:

1. 对象的终结器,如果在这里抛出异常,程序就会就此中断,而不再执行其他非托管资源的清理工作。

2. 对象的Dispose方法,如果在这个方法中抛出异常,那么系统可能会产生两个异常,.NET环境会丢弃第一个异常,并抛出一个新的异常,在程序的任何地方,我们都无法捕获最初的那个异常,因为它被系统“吞掉”了,这会极大的增加错误处理的复杂度。

2. 在委托链中的某个方法,如果抛出了异常,那么委托链中后面的方法就不会再执行。

异常会严重影响一个程序的控制流,在最坏的情况下,任何事情都可能发生,也可能不发生,当抛出异常时,要知道哪些发生了改变或者哪些没有发生改变的唯一方式就是实现“强类型保证”。

转载于:https://www.cnblogs.com/wing011203/archive/2010/03/01/1675789.html

Effective C# Item45 : 优先选择强异常安全保证相关推荐

  1. Effective Java~46. 优先选择Stream 中无副作用的函数

    纯函数(pure function)的结果仅取决于其输入:它不依赖于任何可变状态,也不更新任何状态. 坏味道 // Uses the streams API but not the paradigm- ...

  2. Effective Java之优先使用标准的异常(六十)

    Java平台类库提供了一组基本的未受检的异常,他们满足了绝大部分API的异常抛出异常. 为什么优先使用标准异常 1.它使你的API可读性更强,因为它与程序员习惯的用法一致. 2.异常类越少,程序在类装 ...

  3. Effective Java读书笔记五:异常

    第57条:只针对异常的情况才使用异常 异常是为了在异常情况下使用而设计的,不要将它们用于普通的控制流,也不要编写迫使它们这么做的API. 下面部分来自:异常 如果finally块中出现了异常没有捕获或 ...

  4. [react] props.children.map和js的map有什么区别?为什么优先选择react的?

    [react] props.children.map和js的map有什么区别?为什么优先选择react的? React.Children.map 能够处理未知数据类型,即使 React.childre ...

  5. 陈松松:制作视频优先选择这5种类型,总有一个适合你

    这是我写的第88篇原创视频营销文章 陈松松,6年视频营销实战经验 万事开头难! 就看谁先能挺住! 很多朋友发现制作视频也有很多类型,不知道选择哪种最适合自己,今天我就跟大家详细分享下,当你学习之后,你 ...

  6. 不被消费者优先选择的,不叫品牌,叫商标

    不被消费者优先选择的,不叫品牌,叫商标 周末与客户聊关于"交易成本"的问题后,对我说:真是太有对了!我公司产品的"交易成本"就非常高.我的产品非常好,各项指标都 ...

  7. [转]Effective C# 原则7: 选择恒定的原子值类型数据

    恒定类型(immutable types)其实很简单,就是一但它们被创建,它们(的值)就是固定的.如果你验证一些准备用于创建一个对象的参数,从前面的观点上看, 你知道它在合法(valid)状态.你不能 ...

  8. 在线协助设计软件,figma、sketch、xd哪个才是你的优先选择

    我们今天生活的环境,互联网的快速发展,新的意识形态的不断涌现,工作方式的不断变化,开放的开放.更多的行业和更多的人理解共享的概念,在这样的环境中,效率变得越来越重要.好的工具和工作方法带来先进的生产力 ...

  9. Spring注解依赖注入的三种方式的优缺点以及优先选择

    当我们在使用依赖注入的时候,通常有三种方式: 1.通过构造器来注入: 2.通过setter方法来注入: 3.通过filed变量来注入: 那么他们有什么区别吗?应该选择哪种方式更好? 代码示例: Con ...

最新文章

  1. POJ2594 Treasure Exploration[DAG的最小可相交路径覆盖]
  2. 关于Unity中物理检测的准备
  3. Consul入门05 - 健康检测
  4. vc调用mysql数据库操作例子
  5. php5 php4,自动实现php4和php5环境的切换......
  6. leetcode 1047. 删除字符串中的所有相邻重复项(栈)
  7. 初识Mysql(一)
  8. 你需要知道的Linux 系统下外设时钟管理
  9. mysql 建前缀索引_MySQL_前缀索引_建立
  10. MongoDB 之 你得知道MongoDB是个什么鬼 MongoDB - 1
  11. mt950报文解析_MT700报文升级内容逐项解析
  12. 编译一个.cpp文件的过程
  13. 使用Java生成思维导图
  14. 【题解】洛谷 P1957 口算练习题
  15. keep-alive 的详细介绍
  16. 1608: DNA序列---复制问题 - kmp
  17. html:超文本标记语言的特点
  18. lua_pcall 函数详解
  19. cmd怎么切换mysql目录_mysql 移除服务,并在cmd下切换目录
  20. Linux 系统安装

热门文章

  1. QTreeWidgetItem 类的翻译
  2. 我拿什么融化你,冰冷的电子图书馆?
  3. 大学计算机软件专业生应该学什么(转)
  4. CVPR 2018 LSART:《Learning Spatial-Aware Regressions for Visual Tracking》论文笔记
  5. 在Ubuntu中使用OTB-50测试ECO模型
  6. 2019寒假纪中集训总结学期总结(流水账)
  7. linux 修改网卡mac,Linux修改 网卡物理地址(Mac Address)
  8. sqlserver/mysql按天,按小时,按分钟统计连续时间段数据
  9. 第五章 初始jQuery
  10. day60 Pyhton 框架Django 03