2011-10-26 57 views
3

我的項目中有以下代碼。我是否必須明確處理內部類?如果是這樣的話?處理全部實現IDisposable的嵌套對象

public class Outer : IDisposable 
{ 
    Context context = new Context(); 
    Inner inner; 

    public Outer() 
    { 
     inner = new Inner(context); 
    } 

    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

public class Inner : IDisposable 
{ 
    Context context; 

    public Inner(Context context) 
    { 
     this.context = context; 
    } 

    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

上下文類似於實體框架中的DbContext。

回答

5

那麼,在這種情況下,你需要弄清楚什麼應該實際上「擁有」上下文。如果你在Inner中獲得它,那麼你是否真的需要它在Outer以及?他們中哪一個真的爲他們負責?它看起來像你對我真的想:

public sealed class Outer : IDisposable 
{ 
    private readonly Inner inner; 

    public Outer() 
    { 
     inner = new Inner(new Context()); 
    } 

    public void Dispose() 
    { 
     inner.Dispose(); 
    } 
} 

public sealed class Inner : IDisposable 
{ 
    private readonly Context context; 

    public Inner(Context context) 
    { 
     this.context = context; 
    } 

    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

注意,在作出既OuterInner密封的,沒有必要寫保護Dispose(bool disposing)方法等 - 這是真正爲傳承,成爲一個一般性疼痛。如果您真的需要需要子類OuterInner需要處理更多資源的可能性,則需要更復雜的實現。

我個人嘗試如果可以實現IDisposable,並只在局部變量保持一次性事情using語句。這當然不總是可能的,但它值得嘗試...

+0

+ 1爲簡短使用的使用說明。 – Ucodia

0

在這種特定情況下,您不需要需要,因爲您已經在處理上下文。
但是,無論如何您都應該使用它,以防Inner.Dispose不斷變化。

一般來說,你應該在處理事情方面犯錯。
處理相同的對象兩次不會導致問題。

2

是的,最好是Dipsose inner,只是因爲它實現了IDisposable而Outer擁有它。

事實上,在這個特殊的設置中,它可以被證明是多餘的並不重要。 Inner可能稍後會用於另一種情況,或者自行更改。你應該隔離你的實現。

如果有任何問題,您可能會重新考慮Inner是否應該處理上下文。它不會創建它,而是讓它傳入。如果可以消除Inner.context,則更好。

+0

但是,如果外部和內部都處置了會發生什麼?兩者都試圖處置相同的資源。 – Ucodia

+2

@Ucodia,沒關係。 Dispose()的契約是多次調用應該是安全的。如果有疑問,最好多稱呼它,而不是冒着不稱之的機會。 –

+0

很高興知道。謝謝;) – Ucodia

0

是的,但你也應該正確實施IDisposable。

private bool _disposed; 

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

    protected virtual void Dispose(bool disposing) 
    { 
    if (!_disposed) 
    { 
     if (disposing) 
     { 
      // Managed 
      inner.Dispose(); 
     } 

     // Unmanaged 
    } 

    _disposed = true; 
    } 

    ~Outer() 
    { 
    Dispose(false); 
    } 
+3

沒有跡象表明這裏確實需要一個終結器,或者確實是「完整」模式。就個人而言,我將密封外部和內部,在這一點上,不需要比簡單的Dispose方法更復雜的任何事情。 –

+0

是不是隻能調用無意義(甚至有害)的終結器?終結者是本地資源的最後手段。封裝本地資源的類應實現終結器和IDisposable。只包含其他IDisposable對象的對象不需要終結器,它們可以依靠內部對象的終結器。 – cdleonard

+0

我的答案來自規則CA1063 [鏈接](http://msdn.microsoft.com/en-us/library/ms244737%28v=VS.100%29.aspx)。但我同意,如果你只是密封類型,那麼就不需要完整的模式。 – harlam357

0

基於粘貼的代碼,它是應該處理上下文的Outer類。如果你能保持分配和處理緊密在一起,這是非常好的。上下文對象的生命週期可以非常明智地由Outer類來管理。

處置所有可達到的對象是個不錯的主意。你應該只處理你自己分配的那些對象。

處理內部類也意味着您不能在處理內部對象後使用外部對象。這在您發佈的示例中沒有問題,但通常不會。