2013-09-29 53 views
2

我看着在SO大約像這樣的問題,甚至我發現相當多的,任何那些扔任何光線進入這件事情對我來說。瞭解一次性對象

假設我有這樣的代碼:

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

    protected virtual void Dispose(bool disposing) { } 
} 
  • 我需要在SuperObjectprotected 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   
} 

如何妥善處理在Mooc

+2

當沒有什麼可配置的時候,請不要實施IDisposable。 –

+0

爲什麼當你沒有Finaizer時使用'GC.SuppressFinalize()'? –

+0

@HamletHakobyan這是一個很好的問題,也許你可以在這裏幫忙:http://stackoverflow.com/q/19078536/544283。 – Esteban

回答

6

正常的方法是應用standard IDispoable implementation - 但是,如果你的類或某些類派生自它將使用非託管資源,這確實是只需要 - 這種情況下是INFACT非常罕見(當這種情況確實應用最好將非託管資源包裝在自己的具有完整標準IDisposable實現的類中)。所以假設你沒有處理非託管資源(原始文件句柄,全局分配memeory等),只處理一次性成員(即已管理資源並實現IDisposable)的成員,那麼你可以安全地獲得IDispose的mimimal執行力度 - 是:

只要有一個單一空隙Dispose()方法。在該方法中,只需對可釋放成員調用dispose,然後在基類上處理Dispose。如果你有一個類層次結構可以使這個Dispose虛擬。沒有必要有一個Dispose(布爾)方法。也沒有任何需要檢查對象是否被丟棄 - 因爲你所做的只是在其他對象上調用dipsose,並且這些實現將會執行該檢查。

如果你不喜歡簡單的appraoch,那麼應用標準的完整implimentation(但它不是絕對必要的)。或者做一個標準的implimentation,因爲你遵循推薦的方法,或者做一個簡單的最小(但是正確的)實現 - 但不要在兩者之間做一些事情(即不標準,不簡單或不正確)!

詳情請參見這個問題:Minimal IDispose implimenation for managed resources only

所以你的情況,以下是mimimal執行力度:

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();  
    } 
} 

注意,如果超級對象沒有任何可支配資源,那麼就沒有一點在實現IDisposable和有一個Dispose方法。如果海關只有一次性對象是超類對象,那麼同樣適用於那裏,並且同樣的邏輯再次到達Moo。最後,如果以上全部適用,並且沒有其他一次性物體圍繞您所需要的全部真正需要:

public class Moo : Controller { 
     Custom c; 

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

     public Dispose() { 
      base.Dispose();  
     } 
    } 
+0

此處提供「標準IDispoable實現」鏈接的更新文檔:https://msdn.microsoft.com/en-us/library/fs2xkftw(v=vs.110).aspx –

2

如何正確處理cMoo

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邏輯。只進行一次配置是一個好主意,您可能想要在處理後捕獲使用情況。
  • 省略析構函數(終結)本身就是一種很好的想法,但你現在有沒有派生類應該擁有一個非託管資源額外的約束。