0

I have a string that contains comma seperated email addresses. I then load this into a string array, and from then populate a list which is easier to work with. Once the list is populated, I would like to be able to destroy the now unused string array, because the class still has a lot of work to do before the garbage collector will clean up this waste of memory.

How can I manually destroy this string array...

While reviewing the code, if you have a cleaner more efficient way of populating the list, recommendations are welcome.

Here is code:

  public class EmailReportManager
    {
        private List<string> emailAddresses;

        public EmailReportManager(string emailAddressesCommaSeperatedList)
        {
            loadAddresses(emailAddressesCommaSeperatedList);
        }

        private void loadAddresses(string emailAddressesCommaSeperatedList)
        {
            string[] addresses = emailAddressesCommaSeperatedList.Split(',');
            for (int addressCount = 0; addressCount < addresses.Length; addressCount++)
            {
                this.emailAddresses.Add(addresses[addressCount]);
            }
            //Want to destroy addresses here.....

        }
    }
JL.
  • 78,954
  • 126
  • 311
  • 459

6 Answers6

8

You can't "destroy" the array. Options are:

  • You can clear the array using Array.Clear, so that it won't hold references to any strings any more. This won't reclaim any memory.
  • You can set the variable to null, so that that particular variable doesn't prevent the array from being garbage collected. This won't reclaim any memory.
  • You could call GC.Collect after making sure you don't have any references to the array any more. This will probably reclaim the memory (it's not guaranteed) but it's generally not a good idea. In particular, forcing a full GC regularly can significantly harm performance.

It's worth understanding that in your case you don't need to set the array variable to null - it's about to go out of scope anyway. Even if it wasn't about to go out of scope, if it wasn't going to be used in the rest of the method (and the JIT could tell that) then setting it to null would be pointless. The GC can pretty reliably tell when a variable is no longer relevant. It's rarely a good idea to set a variable to null for the sake of GC - if you find you want to, that's usually an indication that you could refactor your code to be more modular anyway.

It's usually a good idea to just trust the GC. Why do you think the GC isn't going to get round to reclaiming your array, and do you have a really good reason to care?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon, very interesting to know. So I guess the true solution is to try not use that temporary place holder string array, and instead use the AddRange method on the list directly as Kane suggests. – JL. Nov 30 '09 at 07:47
  • @JL: That's still going to create an array - it just doesn't use a separate array variable for it, and it will be more efficient as AddRange knows how to deal with arrays and other `IList` implementations more appropriately. But you should understand that the array is still there, will still need to be garbage collected - and still doesn't need any special treatment. – Jon Skeet Nov 30 '09 at 07:51
4
addresses = null;

Then if you really want to force GC, call this (otherwise, just set it to null and let the GC do its job on its own time):

GC.Collect();

Also see this question: Force garbage collection of arrays, C#

Community
  • 1
  • 1
Yaakov Ellis
  • 40,752
  • 27
  • 129
  • 174
2

I think you can make the code easier to read by using the AddRange method of the List<> class.

public class EmailReportManager 
{ 
    private List<string> emailAddresses = null; 

    public EmailReportManager(string emailAddressesCommaSeperatedList) 
    { 
        this.emailAddresses.AddRange(emailAddressesCommaSeperatedList.Split(","))
    } 
} 
Kane
  • 16,471
  • 11
  • 61
  • 86
  • Wow, that looks very usable indeed, thank you for this great suggestion. – JL. Nov 30 '09 at 07:41
  • Not only it is more readable, it also reduces the number of memory allocations as List knows in advance how many elements there's going to be. – yu_sha Nov 30 '09 at 08:13
1

You don't need to do anything at all to make the array a candidate for garbage collection, and you shouldn't do anything, as everything that you try will only be a waste of time. The garbage collector will collect the array at a convenient time, and in almost every case the garbage collector has a lot more information about the current state of memory usage than what you can possibly anticipate.

From the moment that the array is not used any more (i.e. when you exit the loop where you copy from it), the garbage collector knows that it can be removed. There is no need to clear the reference to the array as the garbage collector already knows that it's no longer used, so the only thing that accompishes is a waste of a few processor cycles. Calling Clear on the Array to remove the references from it is just a waste of time, and will actually keep the array in memory longer as the garbage collector can't remove it until you have cleared it.

Besides, all the strings from the array is now in the list, so the only thing that can be garbage collected is the array of references. All the strings that the references point to are still in use, so collecting the array doesn't free a lot of memory.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
1
private void loadAddresses(string emailAddressesCommaSeperatedList) {
    emailAddresses = new List<String>();
    foreach (string s in emailAddressesCommaSeperatedList.Split(','))
    {
        emailAddresses.Add(s.Trim());
    }
}

the list needs to be instantiated first before using the function add =)

Jronny
  • 2,164
  • 4
  • 30
  • 41
0

Even on Windows XP, you have at last 2GB of memory at your disposal. Are you really that close to using 2GB that you need to worry about releasing the memory a few seconds earlier?

Jason Williams
  • 56,972
  • 11
  • 108
  • 137
  • No, just trying to optimize as much as possible. – JL. Nov 30 '09 at 07:49
  • 3
    Do you have good reason to believe that you *need* to optimize this particularly though? As always, write the clearest code that gets the job done first, then measure whether performance is a problem or not (and if it is, find out *where* you're losing performance before trying to address it). – Jon Skeet Nov 30 '09 at 07:52