談到Dispose,首先須要理解C#的資源數據庫
調用的是微軟類庫或者第三方類庫,通常類庫會提供釋放的方法,即約定爲Dispose,調用便可。api
每一個類庫固然能夠提供各自釋放資源的方法,好比close()、close()、release()、clear()等等。網絡
但爲了統一,微軟提供了IDispose接口,其中只聲明瞭一個void的Dispose()方法。並且還爲實現了IDispose接口的類提供了using釋放資源的語法糖。ide
看代碼:函數
namespace System { [ComVisible(true)] public interface IDisposable { //執行與釋放或重置非託管資源關聯的應用程序定義的任務。 void Dispose(); } }
好比咱們進行一個給圖片加水印的功能,使用System.Drwing類庫中的Image對象。寫代碼的時候,咱們既不手動調用Dispose方法,也不使用using語法。那麼Image對象就一直會留在內存中嗎?
固然不會,Image類有析構函數,在其中調用了Dispose方法。性能
上源碼:this
public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (this.nativeImage != IntPtr.Zero) { try { SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(this, this.nativeImage)); } catch (Exception ex) { if (ClientUtils.IsSecurityOrCriticalException(ex)) { throw; } } finally { this.nativeImage = IntPtr.Zero; } } } ~Image() { this.Dispose(false); }
既然最終析構函數中會釋放資源,那麼咱們是否是不必手動釋放了呢?
這就要說說析構函數了spa
當一個類的實例被GC回收的時候,最終調用的方法。它和構造函數正好相反,後者是在類的實例初始化時調用。線程
它的寫法是這樣子的:code
class Car { ~Car() // finalizer { // cleanup statements... } }
隱式的調用了基類的Finalize方法,因此等價下面的寫法:
protected override void Finalize() { try { // Cleanup statements... } finally { base.Finalize(); } }
Finalize操做呢,有如下限制:
(來源:https://docs.microsoft.com/en-us/dotnet/api/system.object.finalize?view=netframework-4.8 )
簡單理解就是Finalize操做由GC決定,回收的時間不定、順序不定、線程不定。因此析構函數中調用Dispose只是一個保險措施,並不能代替手動釋放資源。
好比數據庫鏈接,你打開鏈接不及時釋放,很快就沒法鏈接新的數據庫了。而此時GC有可能還未執行析構函數。
固然,析構函數在GC回收的時候,還會由於垃圾回收機制有其餘性能問題,詳細咱們在垃圾回收機制的文章中講。
(參考:https://www.viva64.com/en/b/0437/ )
因此,到目前爲止,咱們清楚的知道,對於非託管資源的使用,必定要記得釋放資源。
咱們給被人提供類庫的時候,也明白了到底何時須要實現IDispose接口了。
固然,Dispose的實現已然有套路了,稱之爲Dispose模式,如下是示例:
using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; class BaseClass : IDisposable { // Flag: Has Dispose already been called? bool disposed = false; // Instantiate a SafeHandle instance. SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true); // Public implementation of Dispose pattern callable by consumers. public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // Protected implementation of Dispose pattern. protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) { handle.Dispose(); // Free any other managed objects here. // } disposed = true; } }
喲,剛纔上面的Image類裏面不就是這麼寫的麼? 是呀!