利用IDisposable介面構建包含非託管資源物件

帆帆帆發表於2018-11-12

託管資源與非託管資源

在.net中,物件使用的資源分為兩種:託管資源與非託管資源。託管資源由CLR進行管理,不需要開發人員去人工進行控制,.NET中託管資源主要指“物件在堆中的記憶體”;非託管資源指物件使用到的一些託管記憶體之外的內資源(例如作業系統的資源),CLR不會管理這些資源,需要開發人員去控制。.NET物件使用到的非託管資源主要有I/O流、資料庫連線、Socket連線、視窗控制程式碼等直接與作業系統操作的相關資源。

管理非託管資源

當一個物件不再使用時,我們應該將它使用的非託管資源釋放掉,歸還給作業系統,不然等到CLR將它在隊中的記憶體回收之後。這部分記憶體就會變成不可達狀態。只能等到整個應用程式執行結束後才能歸還給系統。所以我們應當在該物件例項處於“可達”狀態時,既有物件引用指向它時釋放非託管資源。

利用IDisposable介面構造含有非託管資源型別的物件

在.net類庫中有一個IDisposed的介面。幾乎每一個使用非託管資源的型別都應該實現這個介面。那麼如果我們看到實現此介面的型別,也應該第一時間想到該型別中包含非託管資源。IDispose介面是管理物件非託管資源的一種原則。程式碼如下:

interface IDisposable
{
    void Dispose();
}
class ABase:IDisposable
{
    bool _disposed = false;
    public bool Disposed
    {
        get
        {
            return _disposed;
        }
    }
    public ABase(){}

    public void Dispose()
    {
        if(_disposed)
        {
            Dispose(true);
            GC.SuppressFinalize(this);
            _disposed = true;
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if(disposing)
        {
            //release member`s unmanaged resource
        }
        // release ABase`s unmanaged resource
    }
    ~ABase
    {
        Dispose(false);
    }
}
class A : ABase
{
    public A()
    {

    }
    protected override void Dispose(bool disposing)
    {
        if(disposing)
        {
            // release member`s unmanaged resource
        }
        // release A`s unmanaged resource

        // release base class`s unmanaged resource
        base.Dispose(disposing);
    }

}
class B:A
{
    public B()
    {

    }


    public void Dosomething()
    {
        if(Disposed)// if released, throw exception
        {
            throw new ObjectDisposedException(...);
        }
        // do something here
    }

    protected override void Dispose(bool disposing)
    {
        if(disposing)
        {
            // release member`s unmanaged resource
        }
        // release B`s Unmanaged resource
        base.Dispose(disposing);
    }
}

相關文章