using System;
using System.Threading;
//释放模式:确定性地强制对象清理非托管资源。
//一个类型实现了释放模式,那末当对象不再被使用时能够知道如何显示释放掉它所占用的非托管资源。
//所有定义了Finalize方法的类型都应该实现释放模式以便类型的用户能在非托管资源的生存期内拥有更多的控制权。
//一个类型也可以实现释放模式,而不用定义Finalize方法。
//Dispose方法是确定性的并且是可以自由访问的。
//类可以包含一个Dispose方法和一个终结器。
//在一个Dispose方法中,可以释放对象所引用对象的非托管资源和对象本身的非托管资源;
//而终结器只能释放对象本身的非托管资源。
//当一个Dispose方法没有按计划被调用的时候,终结器会被自动调用并且不会被忽略,终结器是一张有效的安全网,。
//当调用了Dispose方法后,不应在该对象上再执行终结过程,第二次重复清除非托管资源可能会产生意想不到的结果。
//通常应该在Dispose方法中禁止使用终结器,在Dispose方法中调用GC.SuppressFinalize方法来禁止终结器。
//
namespace Donis.CSharpBook
{
//实现IDisposable接口以表明该类实现了释放模式
public class Base: IDisposable
{
//无参的公共Dispose方法,可以在确定性垃圾回收中被显示调用,以确保释放/关闭资源,该方法实现了IDisposab接口。
//通过设置参数为true来调用单参数Dispose(bool disposing)
//调用GC.SuppressFinalize方法在将来的垃圾回收中来禁止该对象的终结。
//GC.SuppressFinalize方法会打开与this所引用的对象的一个位标记,当该位标记被打开时,
//CLR不会再把对象的指针从终结链表转移到终结可达队列上,从而阻止对象的Finalize方法被调用,确保对象被立即收集。
public void Dispose()
{
//调用实际执行资源清理的方法
Dispose(true);
GC.SuppressFinalize(this);
}
//可以调用这个 Close公共方法来代替Dispose方法,但是Close方法并不是释放模式正式定义的一部分。
public void Close()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//下面带boolean参数的Dispose方法是放置资源清理代码的地方,执行实际的资源清理任务。
//Finalize方法、无参公共的Dispose方法、公共的Close方法都要调用该方法
//如果该类不是密封类,则该方法应被定义为受保护的虚方法,其派生类为了重写资源清理代码可以重写带boolean参数的Dispose方法
//如果该类是密封类,则该方法应被定义为私有的方法
//disposing = true:该方法在确定性垃圾回收中被显示调用。
// 释放对象所引用对象的非托管资源和对象本身的非托管资源。
//disposing = false:该方法在非确定性垃圾回收中被隐示调用。
// 只能释放对象本身的非托管资源,
// 或者强制执行一些操作。
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// 对象正在被显示释放/关闭,而非执行终结:
//因此在该if语句中访问那些引用其它对象的字段是安全的,这是因为这些对象的Finalize方法还未被调用。
//如果类中的字段所引用的对象实现了释放模式,则应该调用该对象的Dispose()函数,执行被引用托管对象的代码,
//最终释放引用对象本身所使用的资源。
}
// 对象正在被显示释放/关闭,或者被执行终结,按下述方式执行:
//如果资源已经被释放,则直接返回
//设置一个标识来表明资源已经被释放
//释放资源
}
//当垃圾收集执行时,调用Finalize方法,以关闭资源
//终结器通过设置参数为false来调用单参数Dispose(bool disposing)
~Base()
{
//调用实际执行资源清理的方法,将参数设置为false,告诉方法它不应该执行被字段所引用托管对象的代码,
Dispose (false);
}
}
public class Derived: Base
{
//在派生类中不要重写基类的无参Dispose方法和Close方法。
///在派生类中不要重写基类的终结器。终结器的基类实现将正确调用最近派生的Dispose(bool disposing)方法,
//之后这一处理将从最近的派生类向其所有的祖先类传播,因此资源清理以正确的顺序执行。
//最后,在派生类的单参数Dispose(bool disposing)方法中应该调用基类中的同一种方法,释放基类的非托管资源。
{
if (disposing && (components != null))
{
components.Dispose();//释放Form内的其它占用资源
}
base.Dispose(disposing);//释放自己本身的资源
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
// 对象正在被显示释放/关闭,而非执行终结:
//因此在该if语句中访问那些引用其它对象的字段是安全的,这是因为这些对象的Finalize方法还未被调用。
//如果类中的字段所引用的对象实现了释放模式,则应该调用该对象的Dispose()函数,执行被引用托管对象的代码,
//最终释放引用对象本身所使用的资源。
//此方法释放该类型字段所引用的任何实现了释放模式的托管对象所持有的全部资源。
//此方法调用每个引用对象的 Dispose() 方法。
}
// 对象正在被显示释放/关闭,或者被执行终结,按下述方式执行:
//如果资源已经被释放,则直接返回
//设置一个标识来表明资源已经被释放
//释放资源
base.Dispose(disposing);
}
}
}
//范例:FileStream类型派生自实现了Close方法和无参的IDisposable.Dispose方法的Stream类型,
// FileStream类型简单重写了Dispose方法,它接受一个Boolean参数来释放Handle字段包装的非托管文件资源。