2009-05-28 44 views
1

假設我有一個本身包含集合的某種集合;例如Dictionary(Of String,List(Of MyClass))。如果我要完全清除集合,它使任何意義清除父前清除每一個人的孩子集合,就像這樣:清除收藏集 - 首先清除每個項目,或者只是一次清除所有項目?

For Each ListDef As KeyValuePair(Of String, List(Of MyClass)) In MasterDictionary 
    Dim ThisList As List(Of MyClass) = ListDef.Value 
    ThisList.Clear() 
Next 

MasterDictionary.Clear() 

或者這是否真的一事無成不是簡單的多:

MasterDictionary.Clear() 

我在問是否有任何理由 - 性能,安全性,清晰度等 - 使用第一種方法。我自己通常使用第二種方法,因爲我假設它隱式地實現了第一種方法。但我們都知道有時會有多危險;因此這個問題。

編輯:今天,在我自己的應用程序中,我看到了有力的證據表明第一種方法在某些情況下可能更可取。在我的應用程序中,我有一些全局集合(包含列表的字典,如上面的示例代碼中所示),當用戶單擊標有「加載數據」的按鈕時,這些集合將被填充。當用戶點擊「卸載數據」從頭開始時,以前我正在使用上面的第二種方法清除這些集合。

問題是,當用戶第二次點擊「加載數據」時,應用程序會突然變得非常慢。最終它會完成收集再次,但在蝸牛的步伐。我無法弄清楚如何解決這個問題,直到我終於嘗試了上面的第一種方法。現在重新加載和重新填充集合的過程與第一次加載集合的過程一樣快。

根據到目前爲止發佈的答案,這聽起來像我必須有「其他代碼的地方」引用子集合;然而,它並不像我那樣看着我。我引用這些孩子的唯一地方就是我重複他們父母的地方;如果父母被清除,那麼他們應該沒有孩子,代碼是知道的,對嗎?

希望有人可以幫助我理解這些引用是如何仍然徘徊在周圍,或者我正在忽略的是怎麼回事。

+0

根據您在問題中顯示的代碼示例,沒有理由認爲第一個片段與第二個片段的執行方式不同;在任何一種情況下,頂級字典都會在最後被清除,並且沒有任何(據稱)指的是原來在其中的任何元素。 解釋第二次加載時性能差異的唯一方法是發生其他事情,但要確定是否有必要獲取有關您的加載和卸載實際執行的更多信息。 – jerryjvl 2009-05-29 02:24:27

回答

4

在這兩種情況下,您都沒有處理子集合中包含的單個元素的處理問題。在這種情況下,兩者應該相同。

如果其他代碼直接引用任何單獨的子集合,那麼其中一個地方會有所不同。如果您在另一部分代碼中持有對List(Of MyClass)之一的引用,則第一種方法將清除列表中的元素(並影響其他代碼)。第二種方法不會這樣做,因爲它將單獨保留List。

如果沒有其他引用被保存,那麼第二個方法就等待GC清除元素。在這兩種情況下,各個參考資料都將由GC處理,因此性能差異可以忽略不計。就我個人而言,我會使用第二種方法,因爲我相信它更清晰(並且寫得更容易),並且在大多數情況下效果不會令人驚訝,尤其是如果您在其他地方使用列表時。

+0

自從我甚至研究過基於這個問題的代碼以來,它已經很長時間了。回顧一下,我敢肯定,我一定是一直在做你在這裏猜到的 - 在其他地方持有對兒童館藏的引用 - 沒有意識到這一點。老實說,原來的項目是如此的混亂。我剛剛開始,有很多東西需要學習。我現在接受這個答案是爲了後人,因爲我認爲它代表了給這個場景中另一位開發人員的最明智的建議(我甚至不需要*這個代碼來看看自己)。 – 2010-07-23 12:34:49

1

這取決於您的代碼是如何使用的。

如果您在引用任何List(Of MyClass)的地方有其他代碼,那麼顯然,那些列表將使用第一種方法爲其他代碼爲空,而在第一種情況下則不會如此。

如果有任何性能差異,我不知道,我想找出最好的方法是嘗試和分析它。有人可能會認爲第一種方法最初使用的CPU能力稍高一些,但在GC輪迴期間可能會少一些 - 但實際上這種情況下分析會有意義:)。

2

如果沒有其他對'子'集合的引用,那麼'父'集合上的Clear()將最終導致子集合(以及擴展中的項目)被清除。只要沒有任何一個子集合的元素實現IDisposable,我就會說你是安全的,因爲這意味着他們有一些資源被鎖定,並且不妥善處理它們可能會導致問題。