views:

138

answers:

3

Suppose I have a Collection of some kind that itself contains Collections; e.g., Dictionary(Of String, List(Of MyClass)). If I want to clear the Collection entirely, does it make any sense to clear every individual child collection before clearing the parent collection, like so:

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

Or does this really accomplish nothing more than simply:

MasterDictionary.Clear()

I'm asking if there is any reason whatsoever -- performance, safety, clarity, etc. -- to use the first method. I generally use the second method myself, as I'm assuming that it implicitly achieves what the first method does anyway. But we all know how dangerous it is to assume sometimes; hence this question.

EDIT: Today, in my own application, I have seen compelling evidence that the first method might be preferable in certain cases. In my application I have some global collections (Dictionaries containing Lists, as in the example code above) that are populated when the user clicks a button labelled "Load Data". When the user clicks "Unload Data" to start back at the beginning, formerly I was clearing these collections using the second method above.

The problem was that when the user clicked "Load Data" a second time, the application would suddenly become very slow. Eventually it would finish populating the collections again, but at a snail's pace. I couldn't figure out how to fix this problem until I finally tried the first method above. Now reloading and repopulating the collections works just as quickly as loading them the first time.

Based on the answers posted so far, it sounds like I must have "other code somewhere" referencing the child collections; however, it doesn't look to me like I do. The only places I reference these children are where I iterate over their parents; if the parents are cleared, then they should have no children that the code is aware of, correct?

Hopefully someone can help me to understand how either these references are still lingering around, or else what is going on that I am overlooking.

+1  A: 

It depends how your code is otherwise used.

If you have other code somewhere referencing any of the List(Of MyClass) then, obviously, those lists will then be empty to the other code using the first approach, whereas in the first one that will not be the case.

If there are any performance differences, that I do not know, and I suppose the best way to find out is to try and profile it. One could think the first method uses a bit more CPU power initially, but possibly less during a GC round - but really it's a case where profiling would make sense :).

kastermester
+2  A: 

If there are no other references to the 'child' collections, then Clear() on the 'parent' collection will result in the child collections (and by extension, the items in them) being cleaned up - eventually. I'd say you're safe as long as none of the child collections' elements implement IDisposable, as that implies they have some resource locked, and not disposing of them properly could lead to issues down the line.

Harper Shelby
+4  A: 

In both cases, you're not handling any disposal issues of individual elements contained in the child collections. In this case, the two should be identical.

The one place where there would be a difference is if other code has a reference to any of the individual child collections directly. If you hold a reference to one of the List(Of MyClass) in another portion of code, the first method will clear out the elements of the list (and effect your other code). The second method will not do this, since it will leave the List alone.

If no other references are held, then the second method just waits on the GC to cleanup the elements. The individual references are going to be handled by the GC in both cases, so the performance differences will be negligible. Personally, I'd use the second method, since I believe it is more clear (and much easier to write), and the effect will be less surprising in most cases, especially if you're using the list elsewhere.

Reed Copsey
It has been a *long* time since I've even looked at the code I'd based this question on. Looking back, I'm pretty sure I must have been doing what you guess here -- holding references to the child collections elsewhere -- without realizing it. Honestly, the original project was such a big mess; I was just starting out and had much to learn. I'm accepting this answer now for posterity because I think it represents the most sensible advice to give to another developer who might be in this scenario (I don't even *have* this code to look at anymore myself).
Dan Tao