zoukankan      html  css  js  c++  java
  • 第二十章 异常和状态管理

    目录:

    20.1 定义“异常”

    20.2 异常处理机制

    20.3 System.Exception类

    20.4 FCL定义的异常类

    20.5 抛出异常

    20.6 定义自己的异常类

    20.7 用可靠性换取开发效率

    20.8 设计规范和最佳实践

    20.9 未处理的异常

    20.10 对异常进行调试

    20.11 异常处理的性能问题

    20.12 约束执行区域(CLR)

    20.13 代码协定

    20.1 定义“异常”

    异常指成员没有完成它的名称所宣称的行动。

    20.2 异常处理机制

    通过异常处理返回错误报告。

    2.1 try块:如果代码需要执行一般性的资源清理操作,需要从异常中恢复,或者两者都需要,就可以放到try块中。负责清理的代码应放到一个finally块中。try块还可包含也许会抛出异常的代码。负责异常恢复的代码应放到一个或多个catch块中。

    2.2 catch块:catch块包含的是响应一个异常需要执行的代码。catch关键字后的圆括号中的表达式称为捕捉类型。C#要求捕捉类型必须是System.Exception或者它的派生类型。

    在catch块末尾,有三种选择:

    1.从新抛出相同的异常,向调用栈高一层的代码通知该异常的发生。

    2.抛出一个不同的异常,向调用栈高一层的代码提供更丰富的异常信息。

    3.让线程从catch块的底部退出。

    2.3 finally块:finally块包含的是保证会执行的代码。一般在finally块中执行try块的行动所要求的资源清理操作。

    20.3 System.Exception类

     CLR允许异常抛出任何类型的实例——从Int32到String都可以。但是,Microsoft决定部强迫所有编程语言都抛出和捕捉任意类型的异常。因此,他们定义了System.Exception类型,并规定所有CLS相容的编程语言都必须能抛出和捕捉派生自该类型的异常。

    属性名称 访问 类型 说明
    Message 只读 String 包含辅助性文字说明,指出抛出异常的原因。
    Data 只读 IDictionary 引入一个“键/值对”集合。通常,代码在抛出异常前在该程序集合中添加记录项;捕捉异常的代码可在异常恢复中查询记录项并利用其中的信息。
    Source 读/写 String 包含生成异常的程序集的名称
    StackTrace 只读 String 包含抛出异常之前调用过的所有方法的名称和签名,该属性对调试很有用。
    TargetSite   只读 String 包含抛出异常的方法
    HelpLink 只读 String 包含帮助用户理解异常的一个文档的URL
    InnerException 只读 Exception 如果当前异常是在处理一个异常时抛出的,该属性就指出上一个异常时什么。
    HResult 读/写 Int32 跨越托管和本机代码边界时使用的一个32位值。

    抛出异常时,CLR会重置异常起点;也就是说,CLR只记录最新的异常对象抛出位置。

    20.4 FCL定义的异常类

    20.5 抛出异常

    实现自己得方法时,如果方法无法完成方法名所指明得任务,就应抛出一个异常。

    20.6 定义自己的异常类

    从Excetion派生的所有类型都应该时可序列化的,使它们能穿越AppDomain边界或者写入日志/数据库。

    20.7 用可靠性换取开发效率

    面向对象编程极大提升了开发人员的开发效率。开发效率的提升很大一部分来自可组合性,它使代码容易编写,阅读和维护。

    除了代码的可组合性,开发效率的提升还来自编译器提供的各种好用的功能。

    调用方法时插入可选参数

    对值类型的实例进行装箱

    构造/初始化参数数组

    绑定到dynamic变量/表达式的成员

    绑定到扩展方法。

    绑定/调用重载的操作符(方法)

    构造委托对象。

    在调用泛型方法,声明局部变量和使用lambda表达式时推断类型。

    为lambda表达式和迭代器定义/构造闭包类。

    定义/构造/初始化匿名类型及其实例

    重写代码来支持LINQ查询表达式和表达式树

    另外,CLR本身也提供大量辅助来进一步简化编程:

    调用虚方法和接口方法。

    加载程序集并对方法进行JIT编译,会抛出异常。

    访问MarshalByRefObject派生类型的对象时穿越AppDomain边界。

    调用Thread.Abort或AppDomain.Unload时造成线程抛出ThreadAbortException。

    垃圾回收之后,在回收对象的内存之前调用Finalize方法。

    使用泛型类型时,在Loader堆中创建类型对象。

    抛出各种异常。

    为了缓解对状态的破坏,可以:

    执行catch或finally块中的代码时,CLR不允许线程终止。

    可以用System.Diagnostics.Contracts.Contract类向方法应用代码协定

    可以使用约束执行区,它能消除CLR的某些不去确定性。

    取决于状态存在于何处,可利用事务来确保状态要么都修改,要么都不修改。

    将自己的方法设计得更明确。

    20.8 设计规范和最佳实践

     8.1 善用finally块

    确保清理很重要,所以编程语言提供了一些构造来简化代码编写:

    使用lock语句时,锁在finally块中释放。

    使用using语句时,在finally块中调用对象的Dispose方法。

    使用foreach语句时,在finally块中调用IEnumerator对象的Dispose方法。

    定义析构器方法时,在finally块中调用基类的Finalize方法。

    使用这些构造时,编译器将你写的代码放到try块内部,并将清理代码放到finally块中。

    8.2 不要什么都捕捉

    应用程序代码抛出异常,应用程序的另一部分可能预期要捕捉该异常。所以,不要写“大小通吃”的类型,悄悄地吞噬异常,而是应该允许异常在调用栈中向上移动,让应用程序代码针对性地处理它。

    如果异常未得到处理,CLR会终止进程。也可以在一个线程中捕捉异常,在另一个线程中重新抛出异常。为此提供支持的是异步编程模型。

    8.3 得体地从异常中恢复

    捕捉具体异常时,应充分掌握在什么时候会抛出异常,并知道从捕捉的异常类型派生出了哪些类型。

    8.4 发生不可恢复的异常时回滚部分完成的造作——维持状态

    8.5 隐藏实现细节来维持协定

    20.9 未处理的异常

     异常抛出时,CLR在调用栈中向上查找与抛出的异常对象的类型匹配的catch块。没有任何catch块匹配抛出的异常类型,就发生一个未处理的异常。CLR检测到进程中的任何未处理的异常,都会终止进程。未处理异常表明应用程序遇到了未预料到的情况,并认为这是应用程序的真正bug。

    20.10 对异常进行调式

    20.11 异常处理的性能问题

    异常处理的代价:

    非托管C++编译器必须生成代码来跟踪哪些对象被成功构造。编译器还必须生成代码,以便在一个异常被捕捉到的时候,调用每个已构造的对象的析构器。

    托管编译器就要轻松得多,因为托管对象在托管堆中分配,而托管堆受垃圾回收器监视。如对象成功构造,而且抛出了异常,垃圾回收器最终会释放对象得内存。

    20.12 约束执行区域(CLR)

    在CLR中,我们有包含了状态的AppDomain。AppDomain卸载时,它的所有状态都会卸载。所有,如果AppDomain中的一个线程遭遇未处理的异常,可以在不终止整个进程的情况下卸载AppDomain。

    根据定义,CER是必须对错误有适应力的代码块。由于AppDomain可能被卸载,造成它的状态被销毁,所以一般用CER处理由多个AppDomain或进程共享的状态。如果要在抛出了非预期的异常时维护状态,CER就非常有用。有时将这些异常称为异步异常。

    20.13 代码协定

     代码协定提供了直接在代码中声明代码设计决策的一种方式:

    前条件:一般用于对实参进行验证。

    后条件:方法因为一次普通的返回或者抛出异常而终止时,对状态进行验证。

    对象不变性:在对象整个生命期内,确保对象的字段的良好状态。

    代码协定有利于代码的使用,理解,进化,测试,文档和早期错误检测。可将前条件,后条件和对象不变性想象为方法签名的一部分。

    每天学习一丢丢
  • 相关阅读:
    Django models通过DateTimeField保存到MySQL的时间的时区问题
    apache静态文件配置
    Python多线程学习
    Django filter中用contains 在mysql中的问题
    python:open/文件操作
    C++primer plus第六版课后编程题答案
    C++primer plus第六版课后编程题答案8.3
    C++primer plus第六版课后编程题答案8.2
    C++primer plus第六版课后编程题答案8.1
    C++primer plus第六版课后编程题答案7.10
  • 原文地址:https://www.cnblogs.com/terry-1/p/10396985.html
Copyright © 2011-2022 走看看