錯誤2:Finalize和Dispose使用誰?
從上面的論述中我們已經(jīng)很清楚,顯性地調(diào)用finalizer是不允許的,它只能被碎片收集程序調(diào)用。如果希望盡快地釋放一些不再使用的數(shù)量有限的非可管理性資源(如文件句柄),則應(yīng)該使用IDisposable界面,這一界面有個Dispose方法,它能夠幫你完成這個任務(wù)。Dispose是無需等待Finalize被調(diào)用而能夠釋放非可管理性資源的方法。
如果已經(jīng)使用了Dispose方法,則應(yīng)當阻止碎片收集程序再對相應(yīng)的對象執(zhí)行Finalize方法。為此,需要調(diào)用靜態(tài)方法GC.SuppressFinalize,并將相應(yīng)對象的指針傳遞給它作為參數(shù),F(xiàn)inalize方法就能調(diào)用Dispose方法了。據(jù)此,我們能夠得到如下的代碼:
public void Dispose()
{
// 完成清理操作
// 通知GC不要再調(diào)用Finalize方法
GC.SuppressFinalize(this);
}
public override void Finalize()
{
Dispose();
base.Finalize();
}
對于有些對象,可能調(diào)用Close方法就更合適(例如,對于文件對象調(diào)用Close就比Dispose更合適),可以通過創(chuàng)建一個private屬性的Dispose方法和public屬性的Close方法,并讓Close調(diào)用Dispose來實現(xiàn)對某些對象調(diào)用Close方法。
由于不能確定一定會調(diào)用Dispose,而且finalizer的執(zhí)行也是不確定的(我們無法控制GC會在何時運行),C#提供了一個Using語句來保證Dispose方法會在盡可能早的時間被調(diào)用。一般的方法是定義使用哪個對象,然后用括號為這些對象指定一個活動的范圍,當遇到最內(nèi)層的括號時,Dispose方法就會被自動調(diào)用,對該對象進行處理。
using System.Drawing;
class Tester
{
public static void Main()
{
using (Font theFont = new Font("Arial", 10.0f))
{
//使用theFont對象
} // 編譯器將調(diào)用Dispose處理theFont對象
Font anotherFont = new Font("Courier",12.0f);
using (anotherFont)
{
// 使用anotherFont對象
} // 編譯器將調(diào)用Dispose處理anotherFont對象
}
}
在本例的第一部分中,F(xiàn)ont對象是在Using語句中創(chuàng)建的。當Using語句結(jié)束時,系統(tǒng)就會調(diào)用Dispose,對Font對象進行處理。在本例的第二部分,F(xiàn)ont對象是在Using語句外部創(chuàng)建的,在決定使用它時,再將它放在Using語句內(nèi),當Using語句結(jié)束時,系統(tǒng)就會調(diào)用Dispose。
Using語句還能防止其他意外的發(fā)生,保證系統(tǒng)一定會調(diào)用Dispose。
從上面的論述中我們已經(jīng)很清楚,顯性地調(diào)用finalizer是不允許的,它只能被碎片收集程序調(diào)用。如果希望盡快地釋放一些不再使用的數(shù)量有限的非可管理性資源(如文件句柄),則應(yīng)該使用IDisposable界面,這一界面有個Dispose方法,它能夠幫你完成這個任務(wù)。Dispose是無需等待Finalize被調(diào)用而能夠釋放非可管理性資源的方法。
如果已經(jīng)使用了Dispose方法,則應(yīng)當阻止碎片收集程序再對相應(yīng)的對象執(zhí)行Finalize方法。為此,需要調(diào)用靜態(tài)方法GC.SuppressFinalize,并將相應(yīng)對象的指針傳遞給它作為參數(shù),F(xiàn)inalize方法就能調(diào)用Dispose方法了。據(jù)此,我們能夠得到如下的代碼:
public void Dispose()
{
// 完成清理操作
// 通知GC不要再調(diào)用Finalize方法
GC.SuppressFinalize(this);
}
public override void Finalize()
{
Dispose();
base.Finalize();
}
對于有些對象,可能調(diào)用Close方法就更合適(例如,對于文件對象調(diào)用Close就比Dispose更合適),可以通過創(chuàng)建一個private屬性的Dispose方法和public屬性的Close方法,并讓Close調(diào)用Dispose來實現(xiàn)對某些對象調(diào)用Close方法。
由于不能確定一定會調(diào)用Dispose,而且finalizer的執(zhí)行也是不確定的(我們無法控制GC會在何時運行),C#提供了一個Using語句來保證Dispose方法會在盡可能早的時間被調(diào)用。一般的方法是定義使用哪個對象,然后用括號為這些對象指定一個活動的范圍,當遇到最內(nèi)層的括號時,Dispose方法就會被自動調(diào)用,對該對象進行處理。
using System.Drawing;
class Tester
{
public static void Main()
{
using (Font theFont = new Font("Arial", 10.0f))
{
//使用theFont對象
} // 編譯器將調(diào)用Dispose處理theFont對象
Font anotherFont = new Font("Courier",12.0f);
using (anotherFont)
{
// 使用anotherFont對象
} // 編譯器將調(diào)用Dispose處理anotherFont對象
}
}
在本例的第一部分中,F(xiàn)ont對象是在Using語句中創(chuàng)建的。當Using語句結(jié)束時,系統(tǒng)就會調(diào)用Dispose,對Font對象進行處理。在本例的第二部分,F(xiàn)ont對象是在Using語句外部創(chuàng)建的,在決定使用它時,再將它放在Using語句內(nèi),當Using語句結(jié)束時,系統(tǒng)就會調(diào)用Dispose。
Using語句還能防止其他意外的發(fā)生,保證系統(tǒng)一定會調(diào)用Dispose。