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