利用C#实现标准的Dispose模式(2)

2008-02-23 05:05:22来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折


   // 让基类释放自己的资源。基类负责调用GC.SuppressFinalize( )
   base.Dispose( isDisposing );

   // 配置衍生类的被处理过标记
  _disposed = true;
  }
}
   请注意,基类和衍生类都包含该对象的被处理过(disposed)标记。这纯粹是起保护作用。复制这个标记能够封装构成某个对象的任何类释放资源时产生的任何可能的错误。

   您必须编写防护性的Dispose和finalize。对象的处理能够按任意次序进行,您可能会碰到在调用自己类型的成员对象的Dispose()方法之前,该对象已被处理过了。您不应该认为这是问题,因为Dispose()方法会被多次调用。假如他在已被处理过的对象上被调用,他就不执行任何事务。Finalizer(终结器)也有类似的规则。假如您引用的对象仍然存在于内存中,您就没有必要检查空引用(null reference)。但是,您引用的任何对象都可能被处理了,他也可能已被终结了。

   这为我带来了和处理或清除相关的任何方法的最重要的建议:您应该仅仅释放资源,在dispose方法中不要执行任何其他操作。假如您在Dispose或finalize方法中执行其他操作,都可能给对象的生命周期带来严重的不良影响。对象在被构造的时候才"出生",当垃圾收集器收回他们的时候才"死亡"。当您的程式再也不能访问他们的时候,您能够认为他们处于"昏睡"状态。假如您不能到达(reach)某个对象,您就不能调用他的方法,对于任何的意图和目的来说,他是死的。但是带有终结器的对象被宣布死亡之前更有最后一口气。终结器除了清理非受控资源之外不应该执行其他任何操作。假如某个终结器由于什么原因使某个对象又能够到达了,那么该对象就恢复(resurrected)了。即使他是从"昏睡"状态醒来的,他也是"活着"的。下面是个很明显的例子:

public class BadClass
{
  // 保存某个全局对象的引用
  private readonly ArrayList _finalizedList;
  private string _msg;

  public BadClass( ArrayList badList, string msg )
  {
   // 缓冲该引用
   _finalizedList = badList;
   _msg = (string)msg.Clone();
  }

  ~BadClass()
  {
   // 把该对象添加到列表中。这个对象是可到达的,不再是垃圾了。他回来了!
   _finalizedList.Add( this );
  }
}

   当某个BadClass对象执行自己的终结器的时候,他向全局列表上添加了对自己的引用。这仅仅使自己可到达了,他活了过来!但是这样操作所带来的问题使任何人都会感到胆怯。该对象已被终结了,因此垃圾收集器相信不用再次调用他的终结器了。您真的需要终结一个被恢复的对象的时候,终结操作却不会发生了。其次,您的一些资源可能不能用了。GC不会把终结器队列中的对象能够到达的任何对象从内存中移除,但是他可能已终结了这些对象。假如是这样的话,那些对象一定不能再次使用了。尽管BadClass的成员仍然存在于内存中,他们却像被处理过或被终结了相同。在C#语言中没有控制终结次序的途径。您不能使这种构造工作更可靠。不要尝试!

   除了学院的练习作业之外,我从来没有见到过如此明显地使用被恢复对象的代码。但是我看到有些代码有这个倾向,他们在终结器中试图执行某些实际工作,当终结器调用的某些函数保存了对该对象的引用的时候,他就正在把对象变成活动的状态。原则上我们必须很仔细地检查finalizer和Dispose方法中任何代码。假如有些代码除了释放资源之外还执行了其他的操作,我们就需要再检查一次。这些操作在未来可能引起程式bug。请移除这些操作,并确保finalizer和Dispose()方法只释放资源,不作其他任务事务。

   在受控环境中,您不必为自己建立的每个类型编写终结器,您只需要为存储非受控类型,或包含了实现IDisposable接口的成员的类型编写终结器。即使您只需要Disposable接口,无需finalizer,也应该同时实现整个模式。否则,您会使衍生类的标准Dispose思想的实现变得很复杂,从而限制了衍生类的功能。请遵循前面谈到的标准的Dispose思想,这将使您、您的类的用户、从您的类型建立衍生类的用户的生活更加轻松。



标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C#抽象工厂模式的几种实现方法及比较

下一篇: C /CLI中栈对象的设计问题