IDispose和Finalize的区别和联系
今天看代碼,看到IDispose然后牽涉到垃圾回收機(jī)制,最后又到Finalize折騰了一下午,現(xiàn)在終于了解.NET的一些運(yùn)行機(jī)制了。
看到GC.SuppressFinalize方法(MSDN:http://msdn.microsoft.com/zh-cn/library/system.gc.suppressfinalize(v=VS.80).aspx中C#示例),代碼如下:
using System;using System.ComponentModel;
// The following example demonstrates how to use the
// GC.SuppressFinalize method in a resource class to prevent
// the clean-up code for the object from being called twice.
public class DisposeExample
{
// A class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;
// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);//問(wèn)題2:在“Dispose()”中“GC.SuppressFinalize(this);”是什么意思?
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();//問(wèn)題1:也就是為什么GC垃圾回收機(jī)制在回收對(duì)象的時(shí)候只回收或者釋放非托管資源,而不回收托管資源?
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
}
disposed = true;
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);//問(wèn)題1:為什么在析構(gòu)函數(shù)中調(diào)用的是“Dispose(false);”?
}
}
public static void Main()
{
// Insert code here to create
// and use a MyResource object.
}
}
產(chǎn)生了兩個(gè)問(wèn)題(代碼中紅色標(biāo)注區(qū)域):
問(wèn)題1:為什么在析構(gòu)函數(shù)中調(diào)用的是“Dispose(false);”,也就是為什么GC垃圾回收機(jī)制在回收對(duì)
象的時(shí)候只回收或者釋放非托管資源,而不回收托管資源?
問(wèn)題2:在“Dispose()”中“GC.SuppressFinalize(this);”是什么意思?
上網(wǎng)搜了寫資料,終于了解了這種設(shè)計(jì)的用意和優(yōu)點(diǎn):
參考資料:
http://baike.baidu.com/view/4471636.htm
http://www.360doc.com/content/11/0503/18/6075898_114106056.shtml
解答問(wèn)題1:
在.NET的對(duì)象中實(shí)際上有兩個(gè)用于釋放資源的函數(shù):Dispose和Finalize。Finalize的目的是用于釋放非托管的資源,而Dispose是用于釋放所有資源,包括托管的和非托管的。
在這個(gè)模式中,通過(guò)一個(gè)變量“disposing”來(lái)區(qū)分是客戶調(diào)用(true)還是GC調(diào)用(false)。
這是因?yàn)?#xff0c;Dispose()函數(shù)是被其它代碼顯式調(diào)用并要求釋放資源的,而Finalize是被GC調(diào)用的。
在GC調(diào)用的時(shí)候MyResource所引用的其它托管對(duì)象(component)可能還不需要被銷毀,并且即使
要銷毀,也會(huì)由GC來(lái)調(diào)用。因此在Finalize中只需要釋放非托管資源即可。
解答問(wèn)題2:
由于在Dispose()中已經(jīng)釋放了托管和非托管的資源,因此在對(duì)象被GC回收時(shí)再次調(diào)用Finalize是
沒有必要的,所以在Dispose()中調(diào)用GC.SuppressFinalize(this)避免重復(fù)調(diào)用Finalize。
因此,上面的模式保證了:
1、 Finalize只釋放非托管資源;
2、 Dispose釋放托管和非托管資源;
3、 重復(fù)調(diào)用Finalize和Dispose是沒有問(wèn)題的;
4、 Finalize和Dispose共享相同的資源釋放策略,因此他們之間也是沒有沖突的。
在C#中,這個(gè)模式需要顯式地實(shí)現(xiàn),其中C#的~MyResource()函數(shù)代表了Finalize()。
優(yōu)點(diǎn):
1、如果客戶沒有調(diào)用Dispose(),未能及時(shí)釋放托管和非托管資源,那么在垃圾回收時(shí),還有機(jī)會(huì)執(zhí)
行Finalize(),釋放非托管資源,但是造成了非托管資源的未及時(shí)釋放的空閑浪費(fèi)。
2、如果客戶調(diào)用了Dispose(),就能及時(shí)釋放了托管和非托管資源,那么該對(duì)象被垃圾回收時(shí),不回
執(zhí)行Finalize(),提高了非托管資源的使用效率并提升了系統(tǒng)性能。
此外還有Close()方法,此方法一般和Open()方法配合來(lái)使用,對(duì)于數(shù)據(jù)庫(kù)連接,一般可以逆向操作,比如打開->關(guān)閉,關(guān)閉->打開,而對(duì)于文件操作,一般是關(guān)閉文件,相當(dāng)于Dispose(),而且有的用戶更愿意使用Close()來(lái)釋放資源,所以出現(xiàn)了一下這種相當(dāng)于適配器模式的代碼:
public void Close() {Dispose((); }最后還要再說(shuō)一點(diǎn),據(jù)MSDN上說(shuō)C#不允許類實(shí)現(xiàn)Finalize()方法,所以用析構(gòu)函數(shù)來(lái)代替。
記于此,勿忘。
2012.03.07 17:01
轉(zhuǎn)載于:https://www.cnblogs.com/fiteg/archive/2012/03/07/2383864.html
總結(jié)
以上是生活随笔為你收集整理的IDispose和Finalize的区别和联系的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用ul和li实现表格table效果 (转
- 下一篇: auto register volati