2011年3月30日
摘要: 终止化操作 任何封装了非托管资源的类型,如文件、网络连接、套接字等,都必须支持一种称作终止化的操作。终止化操作允许一种资源在它所占用的内存被回收之前执行一些清理工作。要提供终止化操作,我们必须为类型重写一个名为Finalize的方法,该方法在Object中被定义为受保护的虚方法。当垃圾收集器判定一个对象为可收集的垃圾时,它便会调用该对象的Finalize方法。Finalize方法的实现通常便是调用CloseHandle函数。 然而,在C#中实现Finalize方法并非直接重写Finalize方法,C#编译器为我们提供了与C++析构函数类似特殊语法来定义Finalize方法。下例演示了如何定义一 阅读全文
posted @ 2011-03-30 23:20 辛勤的代码工 阅读(372) 评论(0) 推荐(0)
摘要: 每个.Net应用程序都有一组根(root)。一个根是一个存储位置,其中包含着一个指向引用类型的内存指针。该指针或指向一个托管堆中的对象,或被设为null。例如,所有的全局引用类型变量或静态引用类型变量都被认为是根。另外,一个线程堆栈上所有引用类型的本地变量或参数变量也被认为是一个根。最后,在一个方法内,指向引用类型对象的CPU寄存器也是一个根。 当JIT编译器编译一个方法的IL代码时,除了产生本地CPU代码外,JIT编译器还创建一个内部的表。该表中的每一个条目都标识着一个方法的本地CPU指令的字节偏移范围,以及该范围中一组包含根的内存地址(或CPU寄存器)。如下图: 如果在0x0000002. 阅读全文
posted @ 2011-03-30 21:30 辛勤的代码工 阅读(332) 评论(0) 推荐(0)
摘要: 创建、访问、释放资源的几个步骤:调用中间语言(IL)中的newobj指令,为表示某个特定资源的类型实例分配一定的内存空间。调用new操作符时,编译器产生newobj指令。初始化上一步所得的内存,设置资源的初始状态,使其可以为程序所用。类型实例构造器完成这类工作。通过访问类型成员来使用资源。销毁资源状态,执行清理工作。释放内存。引用类型所占的内存由垃圾收集器全权负责释放。值类型所占的内存将随着堆栈空间的消亡而自动消失,无所谓回收。 垃圾收集器对内存中的类型表示着何种资源一无所知,所以垃圾收集器并不清楚怎样执行上述步骤中的第4步。为使资源得到正确清理,开发人员必须自己编写这部分工作的代码。这些代码 阅读全文
posted @ 2011-03-30 20:43 辛勤的代码工 阅读(320) 评论(0) 推荐(0)
摘要: 异常捕获 异常捕获筛选器会判断抛出的异常类型是否和筛选器指定的类型相匹配,如果匹配成功,那么它会返回一个特殊的值通知CLR。CLR首先执行更低层次的堆栈中所有必要的finally块来清理其中启动的操作,展开调用堆栈。然后CLR才执行与抛出异常类型相匹配的catch块中的代码。未处理异常 登记AppDomain.CurrentDomain.UnhandledException事件可以处理当前应用程序域中的由托管代码抛出的未处理异常(不能处理非托管代码抛出的未处理异常)。该事件的委托原型为: public delegate void UnHandledExceptionEventHandler(o 阅读全文
posted @ 2011-03-30 13:48 辛勤的代码工 阅读(747) 评论(0) 推荐(0)
摘要: 类库开发人员使用异常的指导原则避免过多的finally块可以使用using语句来减少finally代码块。避免捕获所有异常如果我们设计的类型是一个类库的一部分,那么它绝对不应该捕获所有的异常(即捕获System.Exception),因为它不可能知道应用程序会如何处理这些异常。如果应用程序代码抛出了一个异常,应用程序的另一部分很可能期望能捕获该异常。这时我们应该让异常按照筛选器的筛选规则沿着调用堆栈向更高一层传递,直至找到能够处理它的应用程序代码。从异常中顺利的恢复我们捕获某个特定的异常时,应该完全理解导致抛出异常的情况,并清楚哪些异常类型继承自我们所捕获的异常。当异常无法修复时,回滚部分完成 阅读全文
posted @ 2011-03-30 11:30 辛勤的代码工 阅读(293) 评论(0) 推荐(0)
摘要: 异常简介 C#只能抛出与CLS兼容的异常,即从System.Exception继承的异常类型。但CLR允许抛出任何类型的对象。C#为我们提供了一种特殊的catch块来捕获与CLS不兼容的异常: catch //这里没有指定异常筛选器{ //这里执行恢复代码 ....} 这样的catch块也可捕获任何与CLS兼容的异常。 finally块中的代码执行的是一些资源清理操作,这些清理操作通常是对应的try块中的行为所需要的。 异常是对程序接口隐含假设的一种违反。 在设计一个类型时,我们应该首先假设类型最常见的使用方式,然后设计其接口使之能够很好地处理这种情况。最后再考虑接口带来的隐含假设,并且当任何 阅读全文
posted @ 2011-03-30 10:50 辛勤的代码工 阅读(497) 评论(0) 推荐(0)