你的位置:首页 > ASP.net教程

[ASP.net教程]编写高质量代码改善C#程序的157个建议——建议49:在Dispose模式中应提取一个受保护的虚方法


建议49:在Dispose模式中应提取一个受保护的虚方法

在标准的Dispose模式中,真正的IDisposable接口的Dispose方法并没有做实际的清理工作,它其实是调用了下面的这个带bool参数且受保护的的虚方法:

    /// <summary>    /// 非密封类修饰用protected virtual    /// 密封类修饰用private    /// </summary>    /// <param name="disposing"></param>    protected virtual void Dispose(bool disposing)    {
      //省略代码 }

之所以提供这样一个受保护的虚方法,是因为考虑了这个类型会被其他类型继承的情况。如果类型存在一个子类,子类也许会实现自己的Dispose模式。受保护的虚方法用来提醒子类:必须在自己的清理方法时注意到父类的清理工作,即子类需要在自己的释放方法中调用base.Dispose方法。

  public class DerivedSampleClass : SampleClass  {    //子类的非托管资源    private IntPtr derivedNativeResource = Marshal.AllocHGlobal(100);    //子类的托管资源    private AnotherResource derivedManagedResource = new AnotherResource();    //定义自己的是否释放的标识变量    private bool derivedDisposed = false;    /// <summary>    ///重写父类Dispose方法    /// </summary>    /// <param name="disposing"></param>    protected override void Dispose(bool disposing)    {      if (derivedDisposed)      {        return;      }      if (disposing)      {        // 清理托管资源        if (derivedManagedResource != null)        {          derivedManagedResource.Dispose();          derivedManagedResource = null;        }      }      // 清理非托管资源      if (derivedNativeResource != IntPtr.Zero)      {        Marshal.FreeHGlobal(derivedNativeResource);        derivedNativeResource = IntPtr.Zero;      }      //调用父类的清理代码      base.Dispose(disposing);      //让类型知道自己已经被释放      derivedDisposed = true;    }  }  public class SampleClass : IDisposable  {    //演示创建一个非托管资源    private IntPtr nativeResource = Marshal.AllocHGlobal(100);    //演示创建一个托管资源    private AnotherResource managedResource = new AnotherResource();    private bool disposed = false;    /// <summary>    /// 实现IDisposable中的Dispose方法    /// </summary>    public void Dispose()    {      //必须为true      Dispose(true);      //通知垃圾回收机制不再调用终结器(析构器)      GC.SuppressFinalize(this);    }    /// <summary>    /// 不是必要的,提供一个Close方法仅仅是为了更符合其他语言(如    /// C++)的规范    /// </summary>    public void Close()    {      Dispose();    }    /// <summary>    /// 必须,防止程序员忘记了显式调用Dispose方法    /// </summary>    ~SampleClass()    {      //必须为false      Dispose(false);    }    /// <summary>    /// 非密封类修饰用protected virtual    /// 密封类修饰用private    /// </summary>    /// <param name="disposing"></param>    protected virtual void Dispose(bool disposing)    {      if (disposed)      {        return;      }      if (disposing)      {        // 清理托管资源        if (managedResource != null)        {          managedResource.Dispose();          managedResource = null;        }      }      // 清理非托管资源      if (nativeResource != IntPtr.Zero)      {        Marshal.FreeHGlobal(nativeResource);        nativeResource = IntPtr.Zero;      }      //让类型知道自己已经被释放      disposed = true;    }    public void SamplePublicMethod()    {      if (disposed)      {        throw new ObjectDisposedException("SampleClass", "SampleClass is disposed");      }      //省略    }  }  class AnotherResource : IDisposable  {    public void Dispose()    {    }  }


如果不为类提供这个受保护的虚方法,很有可能让开发者设计子类的时候忽略掉父类的清理工作。所以要在类型的Dispose模式中提供一个受保护的虚方法。

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技