2012-03-17 42 views
0

想,我有以下類別:如何正確地設計與可支配對象的內部引用的對象

public class DisposableObj : IDisposable 
{ 
    public ChildObj CreateObj(); 
    internal object GetSomething(); 
    // ... 
} 

public class ChildObj 
{ 
    private DisposableObj m_provider; 

    public void DoSomething() 
    { 
     m_provider.GetSomething(); 
    } 
    // ... 
} 

這可能是因爲在某些時候一次性對象將被佈置,但子對象仍然有它的一個引用。

如果此時用戶將調用DoSomething方法,則子對象將嘗試訪問處置的對象。這是不好的因此問題:

我應該如何正確設計這樣的類?

UPDATE /澄清:

我知道的ObjectDisposedException和所有的。我的問題聽起來應該是這樣的:如何正確地通知用戶異常情況以及如何設計類以使其更容易維護?

+1

*不可*不可*引用一個已處理的對象。你無法處理它。正確實現的一次性類引發ObjectDisposedException,您不必提供幫助。 – 2012-03-17 15:41:45

+0

@HansPassant我完全清楚,子對象必須具有對父對象的引用。問題是:如何正確通知用戶異常情況以及如何設計類以使其更容易維護。 – Bobrovsky 2012-03-17 16:39:49

回答

2

雖然這是一個場景,在技術上是可行的,這應該是在你的編程'的特殊狀態 - 我無法想象,你爲什麼會特意設立了這個場景。

說了,使得它在你的設計中明確誰負責處置DisposableObj當 - 如果有孩子訪問釋放的對象之後,你可以認爲這應該導致異常 - 不解決這一點,但拋出異常讓異常冒出來,以便在發現問題時修復邏輯。

執行方面,你可以通過只保留一個布爾值來跟蹤DisposableObj是否被丟棄,以及後來的訪問只是拋出ObjectDisposedException。爲了澄清我的意思DisposableObj對象本身應該跟蹤它的狀態,並拋棄ObjectDisposedException在處理它之後的任何方法調用。

+0

爲什麼跟蹤它?處置對象上的任何方法也應該拋出相同的異常。 – svick 2012-03-17 15:55:21

+1

這就是我的意思:'DisposableObj'應該跟蹤它的狀態並拋出'ObjectDisposedException',也許這句話沒有明確說明 – BrokenGlass 2012-03-17 16:42:15

+0

@BrokenGlass,謝謝,我澄清了我的問題。 – Bobrovsky 2012-03-17 16:42:28

2

想到的第一個問題:
爲您的ChildObj類提供一個名爲ProviderDisposed的內部布爾屬性。
在DisposableObj

將此屬性設置爲從處置真正但是你應該記住創建comunicate到每一個你的主要對象的配置狀態的對象的列表。

List<ChildObj> childsCreated = new List<ChildObj>(); 
public ChildObj CreateObj() 
{ 
    ChildObj obj = new ChildObj(); 
    childsCreated.Add(obj); 
    return obj; 
} 
public void Dispose() 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

protected virtual void Dispose(bool disposing) 
{ 
    // Check to see if Dispose has already been called. 
    if(!this.disposed) 
    { 
     if(disposing) 
     { 
      foreach(ChildObj obj in childsCreated) 
       obj.ProviderDisposed = true; 
      childsCreated = null; 
     } 
     disposed = true; 
    } 
} 

public class ChildObj 
{ 
    private DisposableObj m_provider; 
    private bool m_providerDisposed = false; 

    public bool ProviderDisposed 
    { set { m_providerDisposed = true; } } 

    public void DoSomething() 
    { 
     if(m_providerDisposed == false) 
      m_provider.GetSomething(); 
     // else // as from **@BrokenGlass answer** 
     //  throw new ObjectDisposedException(); 
    } 
    // ... 
} 
+0

謝謝你的例子。但是這種方法不會阻止垃圾收集器正確收集對象嗎?畢竟,每個孩子都有參考父母和父母的參考每個孩子。 – Bobrovsky 2012-03-17 16:37:58

+0

不,我不這麼認爲,當處置DisposableObject時,其對ChildObject列表的內部引用將被刪除。等待被拒絕....但是可以肯定的是,添加一個childsCreated = null;而ChildObject與之前一樣。 – Steve 2012-03-17 16:44:38

+0

你說得對(我在寫評論後得到這個)。但是,雖然家長一次性不處理它必須保持對所有創建的對象的引用。這可能會阻止收集創建的對象。但也許弱引用將在這裏幫助。 – Bobrovsky 2012-03-17 16:47:01

相關問題