.NET Tip of The Day
Learn one new .NET trick every day
Login or Join
.NET Tips & Tricks Community RSS

Those who prefer reading this site through RSS now can also subscribe for updates to .NET Tips & Tricks Community.

How to call a surrogate for Dispose() on StringBuilder objects

A typical use for the StringBuilder type looks like below:

    class Program

    {

        static string UseStringBuilder(string token)

        {

            StringBuilder sb = new StringBuilder();

            int i = 10;

            while (i-- > 0)

            {

                sb.Append(token + '\n');

            }

            string result = sb.ToString();

            return result;

        }

 

        static void Main(string[] args)

        {

            Console.WriteLine(UseStringBuilder("first"));

            Console.WriteLine(UseStringBuilder("second"));

        }

    }

The issue with this code is that when sb goes out of scope it is mark for garbage collection, but the memory stored in it lingers until the garbage collector invokes its finalizer. That could amount to a lot of unused memory and hence might cost you some unnecessary garbage collections by the CLR. Given this behavior it would only look natural to call something like Dispose to take care of the underline memory buffer used in the StringBuilder.

Unfortunately there is no Dispose method for this class, or any method to hint at freeing this unused memory in a deterministic way. The trick to get rid of this memory without invoking the finalizer is to set the Length to 0. The efficient code will become:

    class Program

    {

        static string UseStringBuilder(string token)

        {

            StringBuilder sb = new StringBuilder();

            int i = 10;

            while (i-- > 0)

            {

                sb.Append(token + '\n');

            }

            string result = sb.ToString();

            sb.Length = 0;        // this is the Dispose equivalent

            return result;

        }

 

        static void Main(string[] args)

        {

            Console.WriteLine(UseStringBuilder("first"));

            //no need to call System.GC.Collect() for the unreferenced StringBuilder object

            Console.WriteLine(UseStringBuilder("second"));

        }

    }

via Decebal Mihailescu

Update: use this trick with caution. There's no guarantee that future implementations of the runtime will act as described (tested only on .NET 2.0, 3.0 and 3.5). Only apply if you are working with big strings and have problems with memory/performance. Otherwise you will just complicate your code.
Thanks to Jeff Dean for pointing that out.

10/26/2007
RSS .NET Tip of The Day
Subscribe to receive one tip from the .NET Tips and Tricks Community per day.
Previous Tips of The Day
The best of the .NET Tips & Tricks Community.
.NET Practitioners .NET Tips & Tricks Community
Every .NET practitioner has a trick up in their sleeve. This is the place to share it with other .NET people.
Submit a Tip
Discovered a new trick? Share it with others.
My Tips
Manage tips you authored.