淺析C# Dispose方法的實(shí)現(xiàn)
C# Dispose方法的理解是什么呢?類型的Dispose方法應(yīng)釋放它擁有的所有資源。它還應(yīng)該通過調(diào)用其父類型的Dispose方法釋放其基類型擁有的所有資源。該父類型的 Dispose 方法應(yīng)該釋放它擁有的所有資源并同樣也調(diào)用其父類型的 Dispose 方法,從而在整個(gè)基類型層次結(jié)構(gòu)中傳播此模式。若要確保始終正確地清理資源,Dispose 方法應(yīng)該可以被多次調(diào)用而不引發(fā)任何異常。
Dispose 方法應(yīng)該為它處置的對(duì)象調(diào)用 GC.SuppressFinalize 方法。如果對(duì)象當(dāng)前在終止隊(duì)列中,GC.SuppressFinalize 防止其 Finalize 方法被調(diào)用。請(qǐng)記住,執(zhí)行 Finalize 方法會(huì)大大減損性能。如果您的 Dispose 方法已經(jīng)完成了清理對(duì)象的工作,那么垃圾回收器就不必再調(diào)用對(duì)象的 Finalize 方法。
C# Dispose方法的實(shí)現(xiàn)時(shí)注意
為 System.GC.KeepAlive(System.Object) 方法提供的代碼示例演示了強(qiáng)行垃圾回收如何在回收對(duì)象的成員仍在執(zhí)行時(shí)引起終結(jié)器運(yùn)行。在較長的Dispose方法末尾***調(diào)用KeepAlive方法。
下面的代碼示例旨在闡釋用于為封裝了非托管資源的類實(shí)現(xiàn)Dispose方法的建議設(shè)計(jì)模式。整個(gè) .NET Framework 中都實(shí)現(xiàn)了此模式。
資源類通常是從復(fù)雜的本機(jī)類或 API 派生的,而且必須進(jìn)行相應(yīng)的自定義。使用這一代碼模式作為創(chuàng)建資源類的一個(gè)起始點(diǎn),并根據(jù)封裝的資源提供必要的自定義。不能編譯該示例,也不能將其直接用于應(yīng)用程序。
在此示例中,基類 BaseResource 實(shí)現(xiàn)可由該類的用戶調(diào)用的公共 Dispose 方法。而該方法又調(diào)用 virtual Dispose(bool disposing) 方法(Visual Basic 中為 virtual Dispose(disposing As Boolean))。根據(jù)調(diào)用方的標(biāo)識(shí)傳遞 true 或 false。以虛 Dispose 方法為對(duì)象執(zhí)行適當(dāng)?shù)那謇泶a。
Dispose(bool disposing) 以兩種截然不同的方案執(zhí)行。如果 disposing 等于 true,則該方法已由用戶的代碼直接調(diào)用或間接調(diào)用,并且可釋放托管資源和非托管資源。如果 disposing 等于 false,則該方法已由運(yùn)行庫從終結(jié)器內(nèi)部調(diào)用,并且只能釋放非托管資源。因?yàn)榻K結(jié)器不會(huì)以任意特定的順序執(zhí)行,所以當(dāng)對(duì)象正在執(zhí)行其終止代碼時(shí),不應(yīng)引用其他對(duì)象。如果正在執(zhí)行的終結(jié)器引用了另一個(gè)已經(jīng)終止的對(duì)象,則該正在執(zhí)行的終結(jié)器將失敗。
基類提供的 Finalize 方法或析構(gòu)函數(shù)在未能調(diào)用 Dispose 的情況下充當(dāng)防護(hù)措施。Finalize 方法調(diào)用帶有參數(shù)的 Dispose 方法,同時(shí)傳遞 false。不應(yīng)在 Finalize 方法內(nèi)重新創(chuàng)建 Dispose 清理代碼。調(diào)用 Dispose(false) 可以優(yōu)化代碼的可讀性和可維護(hù)性。
類 MyResourceWrapper 闡釋如何使用 Dispose 從實(shí)現(xiàn)資源管理的類派生。MyResourceWrapper 重寫 virtual Dispose(bool disposing) 方法并為其創(chuàng)建的托管和非托管資源提供清理代碼。MyResourceWrapper 還對(duì)其基類 BaseResource 調(diào)用 Dispose 以確保其基類能夠適當(dāng)?shù)剡M(jìn)行清理。請(qǐng)注意,派生類 MyResourceWrapper 沒有不帶參數(shù)的 Finalize 方法或 Dispose 方法,因?yàn)檫@兩個(gè)方法從基類 BaseResource 繼承這些參數(shù)。
C# Dispose方法的實(shí)現(xiàn)時(shí)注意
此示例中的 protected Dispose(bool disposing) 方法不強(qiáng)制線程安全,因?yàn)闊o法從用戶線程和終結(jié)器線程同時(shí)調(diào)用該方法。另外,使用 BaseResource 的客戶端應(yīng)用程序應(yīng)從不允許多個(gè)用戶線程同時(shí)調(diào)用 protected Dispose(bool disposing) 方法。應(yīng)用程序或類庫的設(shè)計(jì)原則為:應(yīng)用程序或類庫應(yīng)只允許一個(gè)線程擁有資源的生存期,并且應(yīng)在不再需要資源時(shí)調(diào)用 Dispose。根據(jù)資源的不同,在處置資源時(shí)進(jìn)行異步線程訪問可能會(huì)帶來安全風(fēng)險(xiǎn)。開發(fā)人員應(yīng)仔細(xì)檢查自己的代碼,以確定***的方法來強(qiáng)制線程安全
C# Dispose方法的實(shí)現(xiàn)實(shí)例
- // Design pattern for the base class.
 - // By implementing IDisposable, you are announcing that instances
 - // of this type allocate scarce resources.
 - public class BaseResource: IDisposable
 - {
 - // Pointer to an external unmanaged resource.
 - private IntPtr handle;
 - // Other managed resource this class uses.
 - private Component Components;
 - // Track whether Dispose has been called.
 - private bool disposed = false;
 - // Constructor for the BaseResource object.
 - public BaseResource()
 - {
 - // Insert appropriate constructor code here.
 - }
 - // Implement IDisposable.
 - // Do not make this method virtual.
 - // A derived class should not be able to override this method.
 - public void Dispose()
 - {
 - Dispose(true);
 - // Take yourself off the Finalization queue
 - // to prevent finalization code for this object
 - // from executing a second time.
 - 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.
 - protected virtual 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.
 - Components.Dispose();
 - }
 - // Release unmanaged resources. If disposing is false,
 - // only the following code is executed.
 - CloseHandle(handle);
 - handle = IntPtr.Zero;
 - // Note that this is not thread safe.
 - // Another thread could start disposing the object
 - // after the managed resources are disposed,
 - // but before the disposed flag is set to true.
 - // If thread safety is necessary, it must be
 - // implemented by the client.
 - }
 - disposed = true;
 - }
 - // 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.
 - ~BaseResource()
 - {
 - // Do not re-create Dispose clean-up code here.
 - // Calling Dispose(false) is optimal in terms of
 - // readability and maintainability.
 - Dispose(false);
 - }
 - // Allow your Dispose method to be called multiple times,
 - // but throw an exception if the object has been disposed.
 - // Whenever you do something with this class,
 - // check to see if it has been disposed.
 - public void DoSomething()
 - {
 - if(this.disposed)
 - {
 - throw new ObjectDisposedException();
 - }
 - }
 - }
 - // Design pattern for a derived class.
 - // Note that this derived class inherently implements the
 - // IDisposable interface because it is implemented in the base class.
 - public class MyResourceWrapper: BaseResource
 - {
 - // A managed resource that you add in this derived class.
 - private ManagedResource addedManaged;
 - // A native unmanaged resource that you add in this derived class.
 - private NativeResource addedNative;
 - private bool disposed = false;
 - // Constructor for this object.
 - public MyResourceWrapper()
 - {
 - // Insert appropriate constructor code here.
 - }
 - protected override void Dispose(bool disposing)
 - {
 - if(!this.disposed)
 - {
 - try
 - {
 - if(disposing)
 - {
 - // Release the managed resources you added in
 - // this derived class here.
 - addedManaged.Dispose();
 - }
 - // Release the native unmanaged resources you added
 - // in this derived class here.
 - CloseHandle(addedNative);
 - this.disposed = true;
 - }
 - finally
 - {
 - // Call Dispose on your base class.
 - base.Dispose(disposing);
 - }
 - }
 - }
 - }
 - // This derived class does not have a Finalize method
 - // or a Dispose method without parameters because it inherits
 - // them from the base class.
 
C# Dispose方法的實(shí)現(xiàn)以及C# Dispose方法的一些基本內(nèi)容就向你介紹到這里,希望對(duì)你了解和學(xué)習(xí)C# Dispose方法有所幫助。
【編輯推薦】















 
 
 
 
 
 
 