82

I would like to ask what you think is the best way (lasts less / consumes less resources) to clear the contents in order to reuse a StringBuilder. Imagine the following scenario:

StringBuilder sb = new StringBuilder();
foreach(var whatever in whateverlist)
{
  sb.Append("{0}", whatever);
}

//Perform some stuff with sb

//Clear stringbuilder here

//Populate stringbuilder again to perform more actions
foreach(var whatever2 in whateverlist2)
{
  sb.Append("{0}", whatever2);
}

And when clearing StringBuilder I can think of two possibilities:

sb = new StringBuilder();

or

sb.Length = 0;

What is the best way to clear it and why?

Thank you.

EDIT: I ment with current .NET 3.5 version.

David Espart
  • 11,520
  • 7
  • 36
  • 50
  • 4
    Not an answer, but interesting to read: http://bobondevelopment.com/2007/06/11/three-ways-to-clear-a-stringbuilder/ – Philip Wallace Nov 10 '09 at 17:01
  • 1
    What's the reason for not including the StringBuilder.Clear() method as an alternative? – Rune FS Nov 10 '09 at 21:54
  • @Rune: c# 4.0 ain't out yet, it's only in 4.0. On MSDN it says: Supported in: 4. – jcollum Apr 15 '10 at 21:15
  • lucky for me that c#4.0 is out http://blogs.msdn.com/somasegar/default.aspx – Rune FS Apr 16 '10 at 05:05
  • 2
    I wonder why `Length` is writable, but there isn't a read/write "Text" property? Saying `sb.Text = "";` would seem clearer that `sb.Length = 0;`, and a `Text` property would also help in the common scenario where one would otherwise have to say `sb.Length = 0; sb.Append(StuffToStartWith);`. – supercat Aug 14 '12 at 17:26
  • @supercat Probably because a `.Text` property encourages people to accidentially write `sb.Text = sb.Text + nextString;`, defeating the whole point of using a `StringBuilder` in the first place. – LWChris Jul 01 '18 at 16:42
  • @LWChris: It would be reasonable to require that code wanting to set the content use a `Set` method rather than a property, but if one took such an approach I see no reason `Length` shouldn't be treated suitably, especially since there would be uses for different ways of handling lengthening and shortening scenarios. – supercat Jul 01 '18 at 18:38

11 Answers11

76

If you're doing this in .NET 2.0 or 3.5, write an extension method to do it like this:

/// <summary>
///     Clears the contents of the string builder.
/// </summary>
/// <param name="value">
///     The <see cref="StringBuilder"/> to clear.
/// </param>
public static void Clear(this StringBuilder value)
{
    value.Length = 0;
    value.Capacity = 0;
}

Then, you can clear it like this:

someStringBuilder.Clear();

Then, when 4.0 comes out, you can ditch your extension method in favor of the 4.0 version.

UPDATE: It's probably not a good idea to set Capacity to zero. That will guarantee reallocations when you append to the builder, if you're reusing the same instance. However, the memory in the instance of the builder is not released until you set the Capacity to a very small value (such as 1). The default value of the Capacity property is 16. You might want to consider using 16, or (though it's less efficient) setting the capacity twice:

  • Set it to 1 or zero to clear the memory
  • Set it to your original Capacity value (which may differ from 16) to restore it.
Mike Hofer
  • 16,477
  • 11
  • 74
  • 110
  • Neat Method. Just what I was looking for. – abhi Sep 17 '10 at 13:50
  • 15
    I would recommend against clearing the capacity, except when the `StringBuilder` is known to have held something *unusually* big. Especially in earlier versions of .net, if one will be repeatedly building strings of more than 42,500 characters, clearing the buffer after each string will cause extra objects to be allocated in the Large Object Heap every time the buffer has to re-grow. That's a Bad Thing. – supercat Aug 14 '12 at 17:31
  • 2
    Setting the capacity to 0 is an interesting idea. When just using Clear or just setting the length to 0, a memory leak can occur when Insert() is used repeatedly, because the Capacity keeps growing despite the Clear. (see my question: http://stackoverflow.com/questions/29574469/memory-leak-in-stringbuilder-when-using-insert-and-clear – Peter Huber Apr 12 '15 at 00:06
32

In .NET 4.0 you can call sb.Clear() but in older versions you should set sb.Length = 0.

The Clear() method was added in .NET 4.0.

GraemeF
  • 11,327
  • 5
  • 52
  • 76
  • 15
    If you're reusing it wouldn't you want to reuse the buffer? – GraemeF Nov 10 '09 at 17:07
  • 2
    depends on the variance of how much big the string created the first time compared to the string created the second time.. Or at least I would think so – Earlz Nov 10 '09 at 17:08
16

Create the new StringBuilder. The old one maintains resources associated with it (buffer of maximum length, for example) that are best just garbage collected away.

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117
12

From Community Content on MSDN:

To effectively clear your stringbuilder without destroying it use:

 someStringBuilder.length = 0;
 someStringBuilder.capacity = 0;

This destroys both its contents and resizes it to zero. As noted above clear the size can impact smaller applications.

bdukes
  • 152,002
  • 23
  • 148
  • 175
Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142
10

I think you are doing premature optimization.

I would bet that doing sb.Length=0; would be the fastest to keep from creating another object and placing another object aside for GC to eventually collect.

I think creating a new StringBuilder would be the best shot for memory concerns. and setting sb.Length would be the best shot for speed concerns..

Earlz
  • 62,085
  • 98
  • 303
  • 499
5

In .NET Framework 4 new methods were introduced in StringBuilder class. Method name is "Clear". This method helps you to clear or remove values or data from StringBuilder objects.

Here is example for this.

    System.Text.StringBuilder objSB = new System.Text.StringBuilder();
    //Append values
    objSB.Append("This is .Net Blog.");
    objSB.Append("You can get latest C# Tips over here.");

    //Display on screen
    Response.Write(objSB.ToString());
    Response.Write("<br/><br/>");

    //Clear object using Clear method
    objSB.Clear();

    //Append another values
    objSB.Append("This blog is very useful for .Net Beginners");

    Response.Write("After Clear<br/><br/>");
    //Display on screen
    Response.Write(objSB.ToString());
Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Jayesh Sorathia
  • 1,596
  • 15
  • 16
2

If you are looking to reduce memory usage I would use the CLR Profiler to check how much memory your StringBuilder objects are using through their lifecycle using the methods others have described above. Then you can satisfy yourself that the option you choose is suitable for your needs and is releasing the resources you need it to.

Kim R
  • 561
  • 2
  • 13
2

C# In A Nutshell To clear the contents of a StringBuilder, there are two ways:

  1. Set its Length to zero:

    Setting a StringBuilder’s Length to zero doesn’t shrink its internal capacity. So, if the StringBuilder previously contained one million characters, it will continue to occupy around 2 MB of memory after zeroing its Length.

  2. Instantiate a new one:

    If you want to release the memory, you must create a new StringBuilder and allow the old one to drop out of scope (and be garbage collected), with this approach you can solve the previous item problem.

Sina Lotfi
  • 3,044
  • 1
  • 23
  • 30
0

I'd say the best way to clear it is to use sb = new StringBuilder();. That being said, I think it'd be even better if you made a new string builder object altogether.

EDIT

I hope it goes without saying that this is the best solution.

public StringBuilder MakeString(IEnumerable<CoolType> list)
{
    StringBuilder sb = new StringBuilder();

    foreach(var whatever in list)
    {
        sb.Append("{0}", whatever);
    }
}

var sb = MakeString(whateverList);
// Do stuff
// Clear stuff
sb = MakeString(whateverList2);
Matt Grande
  • 11,964
  • 6
  • 62
  • 89
0

Just call Clear() method just set length = 0 , We can set Capacity = 0 also, if we want to save memory

public StringBuilder Clear() {
        this.Length = 0;
        return this;
 }

Ref: In referencesource.microsoft.com

Max CHien
  • 133
  • 1
  • 8
0
// P.S. to be ultra efficient 
// make a good guess at the initial allocation too !!!!
int PerWhatever_SizeEstimate = 4; // a guess of average length... you known your data
StringBuilder sb = new StringBuilder( whateverlist.Length * PerWhatever_SizeEstimate);

// reallocation needed? 
// if you want to be efficient speed and memory wise... 
sb.Length = 0;  // rest internal index but don't release/resize memory
// if a ...BIG... difference in size
if( whatever2.Length < whatever.Length * 2/3  
 || whatever2.Length > whatever.Length * 1.5)
{
    //scale capacity appropriately
    sb.Capaciy = sb.Capacity * whatever2.Length / whatever.Length;
}
PJJ
  • 61
  • 5