1. 程式人生 > >C#中的IDisposable模式用法詳解

C#中的IDisposable模式用法詳解

數據庫 nor 是否 entry block 記錄日誌 自定義 技術分享 ssa

本文實例講述了C#中IDisposable模式的用法,針對垃圾資源的回收進行了較為詳細的講解。分享給大家供大家參考之用。具體方法如下:

首先,對於垃圾回收而言,在C#中,托管資源的垃圾回收是通過CLR的Garbage Collection來實現的,Garbage Collection會調用堆棧上對象的析構函數完成對象的釋放工作;而對於一些非托管資源,比如數據庫鏈接對象等,需要實現IDisposable接口進行手動的垃圾回收。那麽什麽時候使用Idisposable接口,以及如何使用呢?

先來參考一下如下代碼:

public interface IDisposable
{
  void Dispose();
}
public class DisposablClass : IDisposable
{
  //是否回收完畢
  bool _disposed;
  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
  ~DisposableClass()
  {
    Dispose(false);
  }
  //這裏的參數表示示是否需要釋放那些實現IDisposable接口的托管對象
  protected virtual void Dispose(bool disposing)
  {
    if(_disposed) return; //如果已經被回收,就中斷執行
    if(disposing)
    {
      //TODO:釋放那些實現IDisposable接口的托管對象
    }
    //TODO:釋放非托管資源,設置對象為null
    _disposed = true;
  }
}


Dispose()方法

當需要回收非托管資源的DisposableClass類,就調用Dispoase()方法。而這個方法不會被CLR自動調用,需要手動調用。


~DisposableClass(),析構函數

當托管堆上的對象沒有被其它對象引用,GC會在回收對象之前,調用對象的析構函數。這裏的~DisposableClass()析構函數的意義在於告訴GC你可以回收我,Dispose(false)表示在GC回收的時候,就不需要手動回收了。


虛方法Dispose(bool disposing)

通過此方法,所有的托管和非托管資源都能被回收。參數disposing表示是否需要釋放那些實現IDisposable接口的托管對象。

如果disposings設置為true,就表示DisposablClass類依賴某些實現了IDisposable接口的托管對象,可以通過這裏的Dispose(bool disposing)方法調用這些托管對象的Dispose()方法進行回收。

如果disposings設置為false,就表示DisposableClass類依賴某些沒有實現IDisposable的非托管資源,那就把這些非托管資源對象設置為null,等待GC調用DisposableClass類的析構函數,把這些非托管資源進行回收。

另外,以上

把Dispose(bool disposing)方法設置為protected virtual的原因是希望有子類可以一起參與到垃圾回收邏輯的設計,而且還不會影響到基類


。比如有這樣的一個子類:

public class SubDisposableClass : DiposableClass
{
  private bool _disposed; //表示是否已經被回收
  protected override void Dispose(bool disposing)
  {
    if(!_disposed) //如果還沒有被回收
    {
      if(disposiing) //如果需要回收一些托管資源
      {
        //TODO:回收托管資源,調用IDisposable的Dispose()方法就可以
      }
      //TODO:回收非托管資源,把之設置為null,等待CLR調用析構函數的時候回收
      _disposed = true;
    }
    base.Dispose(disposing);//再調用父類的垃圾回收邏輯
  }
}


在.NET 2.0之前,如果一個對象的析構函數拋出異常,這個異常會被CLR忽略。但.NET 2.0以後,如果析構函數拋出異常就會導致應用程序的崩潰。所以,保證析構函數不拋異常變得非常重要

還有,Dispose()方法允許拋出異常嗎?答案是否定的。

如果Dispose()方法有拋出異常的可能,那就需要使用try/catch來手動捕獲

。以下是考慮Dispose()方法有異常可能的寫法:

public class DisposableClass : IDisposable
{
  bool _disposed;
  ......
  protected virtual void Dispose(bool disposing)
  {
    if(_disposed) return;
    if(disposing)
    {
      //TODO:調用托管資源的Dispose()方法進行垃圾回收
    }
    try
    {
      _channelFactory.Close(); //關閉的時候可能會有異常
    }
    catch(Exception ex)
    {
      _log.Warn(ex);//記錄日誌
      try
      {
        _channelFactory.Abort();//丟棄的時候可能會有異常
      }
      catch(Exception cex)
      {
        _log.Warn(cex);//記錄日誌
      }
    }
    _channelFactory = null;
    _disposed = true;
  }
}


總結:


當我們自定義的類及其業務邏輯中引用某些托管和非托管資源,就需要實現IDisposable接口,實現對這些資源對象的垃圾回收。

希望本文所述對大家實現高效率的C#程序設計能夠有所幫助。

除聲明外,跑步客文章均為原創,轉載請以鏈接形式標明本文地址
C#中的IDisposable模式用法詳解

本文地址: http://www.paobuke.com/develop/c-develop/pbk23539.html






相關內容

技術分享C#實現FTP客戶端的案例技術分享ò????éDˉ′????ó???¢μ????????¢?òMessageBoxEx技術分享日常收集C#接口知識(知識全面)技術分享C#實現控制攝像頭的類
技術分享C#修改及重置電腦密碼DirectoryEntry實現方法技術分享C#確保只有一個實例在運行的方法技術分享C#遍歷List並刪除某個元素的方法技術分享C# WinForm捕獲未處理的異常實例解析

C#中的IDisposable模式用法詳解