1

Consider this situation: Form1 builds a List object with tons of elements in it. Then, it has to pass this collection to Form2 via a parameter.

I want to clear everything related to the collection in Form1 after making a hard copy of it in Form2. Let Col1 be the identifier for the collection in Form1.

Since Col1 is passed by reference via parameters, I'm calling Col1.Clear() to clear it of its elements, and then Col1.TrimExcess() to reduce its actual size to 0, so it doesn't keep track of tons of null values.

My intention is to clear all used memory as quickly as possible. Col1.TrimExcess() should clear all used memory, but I'm curious whether Col1 = null would work better in my (or most) case?

  • 4
    I don't understand why you want to pass a huge collection only to clear it where it's "used". Note that passing a reference does not mean that a copy is created. – Tim Schmelter Jul 16 '12 at 14:05
  • 3
    Could you please give a real life example? Your question is a bit abstract. – Flater Jul 16 '12 at 14:06
  • you may want to see this http://stackoverflow.com/questions/823661/explicitly-freeing-memory-in-c-sharp – Gonzalo.- Jul 16 '12 at 14:07
  • @ Tim Schmelter - Another option would be to pass a huge String with more data than the List would contain. Form2 would then build a new List according to the data in the String object. I think passing an already built List would be better. I'm clearing it after making a hard copy of it because it feels rather weird to work inside of Form2 with references to objects in Form1. –  Jul 16 '12 at 14:08
  • or this http://stackoverflow.com/questions/6595617/best-way-to-dispose-a-list – Jake Jul 16 '12 at 14:10
  • @BogdanMarginean: It feels much more weird that you want to create a copy of a list which contains _"tons of objects"_ just because it _feels weird_. Maybe `Form1` is the wrong place. – Tim Schmelter Jul 16 '12 at 14:13
  • 1
    `Col1 = null` is definitely faster than `Col1.Clear()` + `Col1.TrimExcess()` ([`List(T).Clear`](http://msdn.microsoft.com/en-us/library/dwb5h52a.aspx) and [`List(T).TrimExcess`](http://msdn.microsoft.com/en-us/library/ms132207.aspx) are O(n) operations). – Paolo Moretti Jul 16 '12 at 14:17
  • 1
    @Tim Schmelter - you're right. It's exactly like building a truck to transport something, but instead of using the truck you just built, you build another identical truck and destroy the first. Thanks for shedding light on my logical flaw :) Now I'm also considering ditching the extra form and using tabs in the first form. –  Jul 16 '12 at 14:18
  • Thanks for the tips and answers everyone! More than finding out stuff about my original question, I also found out there was a flaw in my logic. I like it when questions lead to this kind of things :) –  Jul 16 '12 at 14:46

3 Answers3

5

I suppose that calling Col1.Clear() to clear it of its elements, and then Col1.TrimExcess() will be a better approach, because Col1 = null will just dereference the list but it will still be in memory till GC does its work.

Calling Col1.Clear() will dereference the items of the list from the list itself and then Col1.TrimExcess() will remove all the empty elements from the list.

So this way it will remove references of everything in the memory.

Hope it helps...

Virus
  • 2,445
  • 1
  • 14
  • 17
  • Indeed, what you say is true. But now that Paolo left a comment to my question, I'm trying to weigh both solutions: setting the list to null is done in constant (O(1)) time but the GC will take its time to show up (how much it will take is still unknown to me, I have to do some research). Manually clearing everything is done in 2 x O(n) but there's no need to wait for the GC. –  Jul 16 '12 at 14:35
  • Clearing the list manually isn't O(2n) since n would be 0 for `TrimExcess()` because you just cleared it with `Clear()`. But anyway, I guess that relying on the GC gives better performance since it's completely optimized to do so. Also, it's baked into the runtime environment so its probably written in C or something which is very fast. – Jupiter Sep 30 '13 at 22:52
2

I'm guessing you are doing this so you can "prepare" stuff in form1, then pass the ready contents to Form2 in order to avoid some kind of lagging or something, am I correct? In any case, there are a couple of issues to consider:

As Tim Schmelter points out, adding a reference to a list "X" from form 2 does not create a copy - only a new reference to X. Removing the reference to X from form 2 should also not reduce memory, since X will still exist - there will just be one thing less with a pointer to it. If you do create a hard copy of the list however, then you might indeed save some memory by removing all referenced to the original list and the data it contains. (Note however, that deep copying a list is not always straight foreward...)

As for weather to use clear() and TrimExcess(), I would generally assume that these are built in for a good reason, and expect them to perform quite well. In any case, I highly doubt that they will affect the speed of your code in any significant way.

Also, if you should choose to use col = null, you will end up with a variable with a null value (obviously...), while the other option will end up with an empty (but non-null) list. If I'm not mistaken, the equivalent of trimming the list to zero length "manually" is not to set it to null, but to point it to a new (empty) list: col = new List(), but I doubt that would save you any CPU cycles.

In short, I would recommend you go ahead like you started, and use the built in methods.

Community
  • 1
  • 1
Kjartan
  • 18,591
  • 15
  • 71
  • 96
  • I was making the copy via Col2.AddRange(Col1); I was passing the collection to Form2 because Form1 was running a filter on the initial data, and Form2 was running a second filter on the previously filtered data. But I think this kind of interface fragmentation is wrong, because the filters are not that much unrelated. I'll use tabs on one form only. I got my answers and yours is the most descriptive. I'll accept it as valid. –  Jul 16 '12 at 14:45
  • Glad to be of help (and thanks for accepting the answer, I appreciate it). – Kjartan Jul 17 '12 at 13:15
  • "In any case, I highly doubt that they will affect the speed of your code in any significant way." This is simply not true. Both `Clear()` and `TrimExcess()` are O(n) operations although n would be 0 for the latter since the list would be empty. – Jupiter Sep 30 '13 at 22:46
1

Accordingly to MSDN:

To reset a List to its initial state, call the Clear method before calling the TrimExcess method. Trimming an empty List sets the capacity of the List to the default capacity.

So I guess your approach is correct.

Bruno Brant
  • 8,226
  • 7
  • 45
  • 90