2010-09-01 85 views
2

我有一個使用一些底層的本地資源,並有一個指針指向下一個實例,這是我通過類似迭代的一個對象:如何處理通過其Next屬性迭代的對象?

MyObject begin = null; 

try 
{ 
    begin = GetFirst(); 

    while (begin != null) 
    { 
     MyObject next = begin.Next(); 
     // do something with begin 
     begin.Dispose(); 
     begin = next; 
    } 
} 
finally 
{  
    if (begin != null) 
    { 
     begin.Dispose(); 
    } 
} 

我得到的代碼分析問題:

CA2202 :Microsoft.Usage:Object'begin'可以在方法'x()'中多次處理。爲避免生成System.ObjectDisposedException,您不應該在對象上多次調用Dispose。

任何想法如何擺脫這個錯誤,而不是壓制它?

+0

在'begin.Dispose()'行後面緊挨着一個'begin = null;'是否需要處理? – kbrimington 2010-09-01 23:36:00

+0

@kbrimington:不,那是我的第一個想法。沒有運氣:( – esac 2010-09-01 23:41:25

+0

我會考慮整個迭代過程是否可以封裝在一些更高級別的生成器類中,然後在生成元素的整個結果後負責清理。 – 2010-09-02 01:37:50

回答

4

在我看來,你最後一塊代碼是不必要的。如果begin != null,那麼你的while循環應該繼續,不?

UPDATE:它看起來像你試圖確保begin的最後獲得的價值被拋棄,以防萬一拋出異常。在using塊年底前分配給next的最後一個值:試試這個:

MyObject begin = GetFirst(); 

while (begin != null) 
{ 
    MyObject next; 
    using (begin) 
    { 
     next = begin.Next(); 
     // do something with begin 
    } 

    begin = next; 
} 

注意,在上述建議,它實際上還是發生了,你最終與未予處置的對象。您的原始問題沒有涵蓋這種情況,所以我沒有在上面的建議中提到它。不過,這是一個需要考慮的問題,如果這是一個潛在的問題。

0

看起來代碼分析認爲在Dispose()方法中可能發生異常。如果是這樣的話,你可以輸入一個已經放置的儘管非空引用begin的finally塊。

請注意,如果您打算將呼叫包裝爲begin.Dispose()以進行其他錯誤捕獲和處理,則我只會傾向於@ Dan的這種方法。國際海事組織,丹的解決方案更優雅。

這是一個嘗試,最後的辦法,消除了警告:

MyObject begin = GetFirst(); 
MyObject next = null; 

while (begin != null) 
{ 
    try 
    { 
     next = begin.Next(); 
     // do something with begin 
    } 
    finally 
    { 
     begin.Dispose(); 
     begin = next; 
    } 
} 
0

你顯然有一些機制來識別第一項目鏈,可能還有一些其他的物體或一些靜態存儲被第一項?

如何在你的代碼與原先調用dispose:

GetFirst().Dispose(); 

那麼對於Dispose方法唯一的責任是處理當前的項目和它的孩子們:

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

這消除了任何需要在dispose方法中循環。我也看看dispose pattern