熱點推薦:
您现在的位置: 電腦知識網 >> 操作系統 >> Windows優化 >> 正文

通過C#中的解構器編寫可靠高效的應用程序

2022-06-13   來源: Windows優化 

  引言
    在企業應用開發世界性能靈活性和安全性是最重要的我作為一個VC++程序員開始我的職業生涯並且在一個晴朗的早晨我被轉到了Web開發部像每個C++程序員一樣我也很失落我想每個像TomDick甚至Harry能用HTML編程然而不久我就發現真正的挑戰是生產高性能的靈活的可靠的應用程序綜上所述Web環境松耦合的不分國界的本質將使你永遠神往
  
    為了制作高性能的靈活的應用程序用最優化的方式使用你的資源是至關重要的一個技巧是盡可能晚地使用你的資源並且在使用後盡快釋放它我在這裡的意圖是描述在C#中的對象清除機制
  
  解構器
    我們知道解構器被用來清除類的事例當我們在C#中使用解構器是我們必須記住以下幾點
  
  一個類只能有一個解構器
  解構器不能被繼承或重載
  解構器不能被調用他們是自動被(編譯器)調用的
  解構器不能帶修飾或參數
  下面是類MyClass解構器的一個聲明
  
  ~ MyClass() 
  { 
    // Cleaning up code goes here 
  }
  
    程序員不能控制解構器何時將被執行因為這是由垃圾收集器決定的垃圾收集器檢查不在被應用程序使用的對象它認為這些條件是符合清楚的並且收回它們的內存解構器也在程序退出時被調用當解構器執行時其背後所發生的那一幕是解構器隱式調用對象基類的ObjectFinalize方法因此上述解構器代碼被隱含轉化成
  
  protected override void Finalize() 
  { 
    try 
    { 
     // Cleaning up  
    } 
    finally 
    { 
     baseFinalize(); 
    }
  }
  
    現在讓我們看一個解構器怎樣被調用的例子我們有三個類AB和C B派生自AC派生自B每個類有它們自己的構造器和解構在類App的main函數中我們創建C的對象
  
  using System; 
  class A 
  { 
   public A() 
   { 
   ConsoleWriteLine(Creating A); 
   } 
   ~A() 
   { 
   ConsoleWriteLine(Destroying A); 
   } 
  } 
   
  class B:A 
  { 
   public B() 
   { 
   ConsoleWriteLine(Creating B); 
   } 
   ~B() 
   { 
   ConsoleWriteLine(Destroying B); 
   } 
   
  } 
  class C:B 
  { 
   public C() 
   { 
   ConsoleWriteLine(Creating C); 
   } 
   
   ~C() 
   { 
   ConsoleWriteLine(Destroying C); 
   } 
  } 
  class App 
  { 
   public static void Main() 
   { 
   C c=new C(); 
   ConsoleWriteLine(Object Created ); 
   ConsoleWriteLine(Press enter to Destroy it); 
   ConsoleReadLine(); 
   c=null; 
   //GCCollect(); 
   ConsoleRead(); 
   } 
  }
   
    正如我們預料的基類的構造器將會被執行並且程序會等待用戶按enter當這個發生我們把類C的對象置為null但解構器沒有被執行!!??正像我們所說的程序員無法控制解構器何時被執行因為這是由垃圾搜集器決定的但程序退出時解構器被調用了你能通過重定向程序的o/p到文本文件來檢查這個我將它輸出在這裡注意到基類的解構器被調用了因為在背後baseFinalize()被調用了
  
  Creating A
  Creating B
  Creating C
  Object Created
  Press enter to Destroy it
  Destroying C
  Destroying B
  Destroying A
   
    所以如果一旦你使用完對象你就想調用解構器你該怎麼做?有兩個方法
  
  調用垃圾搜集器來清理
  
  實現IDisposable的Dispose方法
  
  調用垃圾搜集器
  
    你能通過調用GCCollect方法強制垃圾搜集器來清理內存但在大多數情況下這應該避免因為它會導致性能問題在上面的程序中在GCCollect()處移除注釋編譯並運行它現在你能看到解構器在控制台中被執行了
  
  實現IDisposable接口
  
   
  
    IDisposable 接口包括僅有的一個公共方法其聲明為void Dispose()我們能實現這個方法來關閉或釋放非托管資源如實現了這個接口的類事例所控制的文件和句柄等這個方法被用做所有任務聯合對象的資源釋放當實現了這個方法對象必須尋求確保所有擁有的資源被繼承結構中關聯的資源也釋放(不能把握翻不出來)
  
   
  
  class MyClass:IDisposable 
  { 
    public void Dispose() 
   { 
   //implementation 
   } 
  }
  
    當我們實現了IDisposable接口時我們需要規則來確保Dispose被適當地調用
  
  聯合使用解構器和IDisposable接口
  
  Public class MyClass:IDisposable 
  { 
   private bool IsDisposed=false; 
   public void Dispose() 
   { 
   Dispose(true); 
   GCSupressFinalize(this); 
   } 
   protected void Dispose(bool Diposing) 
   { 
   if(!IsDisposed) 
   { 
   if(Disposing) 
   { 
    //Clean Up managed resources 
   } 
   //Clean up unmanaged resources 
   } 
   IsDisposed=true; 
   } 
   ~MyClass() 
   { 
   Dispose(false); 
   } 
  }
  
    在這裡重載了Dispose(bool)來做清理工作並且所有的清理代碼都僅寫在這個方法中這個方法被解構器和IDisposableDispose()兩著調用我們應該注意Dispose(bool)沒有在任何地方被調用除了在IDisposableDispose()和解構器中
  
    當一個客戶調用IDisposableDispose()時客戶特意地想要清理托管的和非托管資源並且因此完成清理工作有一件你必須注意的事情是我們在清理資源之後立即調用了GCSupressFinalize(this)這個方法通知垃圾搜集器不需要調用解構器因為我們已經做了清理
  
    注意上面的例子解構器使用參數false調用Dispose這裡我們確信垃圾搜集器搜集了托管資源我們僅僅做非托管資源的清理
  
  結論
    盡管如此我們花費一些時間實現IDisposable接口如果客戶不能合適地調用它們會怎樣?為此C#有一個酷的解決方案using代碼塊它看起來像這樣
  
  using (MyClass objCls =new MyClass()) 
  { 
   
  }

From:http://tw.wingwit.com/Article/os/youhua/201311/10757.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.