C#资源释放方法实例分析

2019-12-26 18:07:38于丽

二、Disposable 模式

1.在.NET种由于当对象变为不可访问后将自动调用Finalize方法,所以我们手动调用IDisposable接口的Dispose方法和对象终结器调用的方法极其类似,我们最好将他们放到一起来处理。

我们首先想到的是重写Finalize方法,如下:


protected override void Finalize()
{
  Console.WritleLine("析构函数执行...");
}

当我们编译这段代码的时候,我们发现编译器会报如下的错误: 这是因为编译器彻底屏蔽了父类的Finalize方法,编译器提示我们如果要重写Finalize方法我们要提供一个析构函数来代替,下面我们就提供一个析构函数:

~TestClass() { Console.WriteLine("析构函数执行..."); }

实际上这个析构函数编译器会将其转变为如下代码:


protected override void Finalize()
{
  try {
    Console.WritleLine("析构函数执行...");
  }
  finally {
    base.Finalize();
  }
}

2.然后我们就可以将Dispose方法的调用和对象的终结器放在一起来处理,如下:


public class TestClass: IDisposable
{
  ~TestClass()
  {
    Dispose();
  }
  public void Dispose()
  { // 清理资源
  }
}

3.上面实现方式实际上调用了Dispose方法和Finalize方法,这样就有可能导致做重复的清理工作,所以就有了下面经典Disposable 模式:


private bool _isDisposed = false;
public void Dispose()
{
  Dispose(true);
  GC.SupressFinalize(this);
}
protected void Dispose(bool Diposing)
{
  if(!_isDisposed)
  {
    if(Disposing)
    {
      //清理托管资源
    }
    //清理非托管资源
  }
  _isDisposed=true;
}
~TestClass()
{
  Dispose(false);
}

3.1. SupressFinalize方法以防止垃圾回收器对不需要终止的对象调用 Object.Finalize()。

3.2. 使用IDisposable.Dispose 方法,用户可以在可将对象作为垃圾回收之前随时释放资源。如果调用了 IDisposable.Dispose方法,此方法会释放对象的资源。这样,就没有必要进行终止。IDisposable.Dispose 应调用 GC.SuppressFinalize 以使垃圾回收器不调用对象的终结器。

3.3.我们不希望Dispose(bool Diposing)方法被外部调用,所以他的访问级别为protected 。如果Diposing为true则释放托管资源和非托管资源,如果 Diposing等于false则该方法已由运行库从终结器内部调用,并且只能释放非托管资源。