代码改变世界

Effective C# 学习笔记(十七)标准析构模式的实现

2011-07-08 22:13  小郝(Kaibo Hao)  阅读(420)  评论(0编辑  收藏  举报

标准的析构模式的实现要点如下:

 

  1. 每个使用非托管资源的类都应实现IDisposable接口

实现该接口的内部逻辑应包括以下几点

  1. 释放所有非托管资源
  2. 释放所有托管资源
  3. 设置一个标志位,说明该对象已被析构。当然还需要校验该对象的当前状态并在被其他调用时throw ObjectDisposedExption
  4. 调用GC.SuppressFinalize(this)来通知GC去释放

IDisposable就一个方法,其代码如下:

 

public interface IDisposable

{

void Dispose();

}

 

  1. 每个使用非托管资源的类都应实现finalizer

GC运行的时候,他会立即将没有finalizer的垃圾对象回收移除,剩下的对象会被放到到一个析构队列中,然后GC会创建一个新线程去调用队列中每个对象的finalizer

 

  1. 对于子类的析构,需重载其父类的Dispose方法,并在其方法中析构自己的托管和非托管对象,并且不要忘记调用父类的析构方法。

你可以在父类中,定义一个虚方法来定义负父类的析构方法代码如下:

// isDisposingfalse的时候只析构你的非托管资源,为true的时候析构所有托管及非托管资源

protected virtual void Dispose(bool isDisposing)

 

下面是一段完整的实现:

public class MyResourceHog : IDisposable

{

// Flag for already disposed

private bool alreadyDisposed = false;

// Implementation of IDisposable.

// Call the virtual Dispose method.

// Suppress Finalization.

public void Dispose()

{

Dispose(true);

GC.SuppressFinalize(this);

}

// Virtual Dispose method

protected virtual void Dispose(bool isDisposing)

{

// Don't dispose more than once.

if (alreadyDisposed)

return;

if (isDisposing)

{

// elided: free managed resources here.

}

// elided: free unmanaged resources here.

// Set disposed flag:

alreadyDisposed = true;

}

  ~MyResourceHog ()

  {

    //elided: free managed resources here

  }

public void ExampleMethod()

{

if (alreadyDisposed)

throw new ObjectDisposedException(

"MyResourceHog",

"Called Example Method on Disposed object");

// remainder elided.

}

}

//继承的类

public class DerivedResourceHog : MyResourceHog

{

// Have its own disposed flag.

private bool disposed = false;

protected override void Dispose(bool isDisposing)

{

// Don't dispose more than once.

if (disposed)

return;

if (isDisposing)

{

// TODO: free managed resources here.

}

// TODO: free unmanaged resources here.

// Let the base class free its resources.

// Base class is responsible for calling

// GC.SuppressFinalize( )

base.Dispose(isDisposing);

// Set derived class disposed flag:

disposed = true;

}

}

注意:这里子类和父类中都定义了是否已析构的标志位,这时为了保证该对象在各种类型的构造下都释放了资源。

 

  1. 不要在析构方法里添加与析构无关的代码,否则会引起严重的问题