簡體   English   中英

了解一次性物品

[英]Understanding disposable objects

我已經在 SO 中查看了類似這樣的問題,即使我發現了很多,其中任何一個都為我解決了這個問題。

讓我們假設我有這個代碼:

public class SuperObject : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) { }
}
  • 我需要在SuperObject上使用protected virtual void Dispose(bool)嗎? 因為那里真的沒有什么可以處理的。
public interface ICustom : IDisposable { }
public class Custom : ICustom
{
    public SuperObject Super { get; protected set; }

    public Custom()
    {
        Super = new SuperObject();
    }

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

    public virtual void Dispose(bool disposing)
    {
        if (!disposing) return;

        if (Super != null)
            Super.Dispose();
    }
}
public class Foo
{
    public Foo()
    {
        using (var c = new Custom())
        {
            //do magic with c
        }
    }
}

現在,如果我想/需要/嘗試在System.Web.Mvc.Controller這樣已經實現並已經實現 IDisposable 的類上使用Custom會發生什么?

public class Moo : Controller
{
    Custom c;

    public Moo()
    {
        c = new Custom();
    }

    // Use c throughout this class        
}

如何在Moo正確處理c

正常的方法是應用標准的 IDisposable 實現- 但是,這實際上只有在您的類或從它派生的某個類將使用非托管資源時才是必要的 -這種情況實際上非常罕見(當這種情況確實適用時,最好將其包裝起來)類中的非托管資源,該類具有完整的標准 IDisposable 實現)。

因此,假設您不處理非托管資源(原始文件句柄、全局分配的內存等)並且只處理一次性成員(即具有托管資源並實施 IDisposable),那么您可以安全地獲得一種最小實現的方法IDispose - 即:

只需一個 void Dispose() 方法。 在該方法中,只需在可處理成員上調用 dispose,然后在基類上調用 Dispose(如果它是可處理的)。 如果您有一個類層次結構,可以將這個 Dispose 設為虛擬。 不需要有 Dispose(bool) 方法。 也不需要檢查對象是否已被處理——因為您所做的只是在其他對象上調用 dipsose,而那些實現將進行該檢查。

如果您不喜歡最簡單的方法,則應用標准的完全實現(但這不是絕對必要的)。 即要么做一個標准的實現,因為你堅持遵循推薦的方法,要么做一個簡單的最小(但正確)的實現 - 但不要在兩者之間做任何事情(即不標准,不簡單或不正確)!

有關更多詳細信息,請參閱此問題: Minimal IDispose implimenation for managed resources only

因此,在您的情況下,以下是最小的實現:

public class SuperObject : IDisposable {
    public void Dispose() {
        // Dispose code...just call dispose on dispoable members.
        // If there are none then no need to implement IDisposable!
    }
}

public interface ICustom : IDisposable { }
public class Custom : ICustom {
    public SuperObject Super { get; protected set; }

    public Custom() {
        Super = new SuperObject();
    }

    public void Dispose() {
        if (Super != null)
            Super.Dispose();
    }
}  

public class Moo : Controller {
    Custom c;

    public Moo() {
        c = new Custom();
    }

    public Dispose() {
        if (c!=null)
            c.Dispose()
        base.Dispose();       
    }
}

請注意,如果 Super 對象沒有任何一次性資源,那么實現 IDisposable 和擁有 Dispose 方法就沒有意義。 如果海關唯一的一次性對象是 SuperObject,那么同樣適用於那里,同樣的邏輯再次適用於 Moo。 最后,如果以上所有內容都適用並且周圍沒有其他一次性物品,那么您真正需要的是:

  public class Moo : Controller {
        Custom c;
    
        public Moo() {
            c = new Custom();
        }
    
        public Dispose() {
           base.Dispose();       
        }
    }

如何在Moo正確處理c

public class Moo : Controller
{
    Custom c;

    public Moo()
    {
        c = new Custom();
    }

    // Use c throughout this class    


    protected override Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
           c.Dispose()
    }
}

這也回答了您的第一個問題, Controller需要使其Dispose(bool)方法protected virtual否則上述方法是不可能的。

但有幾點說明:

  • 你沒有任何isDisposed邏輯。 只進行一次處理是個好主意,您可能希望捕獲使用后處理。
  • 省略析構函數(終結器)本身是一個好主意,但您現在有額外的約束,即派生類不應擁有非托管資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM