best way to clear contents of .NET's StringBuilder
Asked Answered
S

12

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.

Serafinaserafine answered 10/11, 2009 at 16:55 Comment(7)
Not an answer, but interesting to read: bobondevelopment.com/2007/06/11/…Schopenhauerism
What's the reason for not including the StringBuilder.Clear() method as an alternative?Swear
@Rune: c# 4.0 ain't out yet, it's only in 4.0. On MSDN it says: Supported in: 4.Mcgruder
lucky for me that c#4.0 is out blogs.msdn.com/somasegar/default.aspxSwear
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);.Levins
@Levins 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.Formyl
@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.Levins
D
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.
Denise answered 10/11, 2009 at 17:4 Comment(3)
Neat Method. Just what I was looking for.Oedipus
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.Levins
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: #29574969Puree
B
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.

Bukharin answered 10/11, 2009 at 16:58 Comment(2)
If you're reusing it wouldn't you want to reuse the buffer?Bukharin
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 soMenial
F
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.

Fremont answered 10/11, 2009 at 16:58 Comment(0)
L
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.

Laws answered 10/11, 2009 at 16:59 Comment(0)
M
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..

Menial answered 10/11, 2009 at 16:59 Comment(0)
G
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());
Gaza answered 5/7, 2012 at 8:0 Comment(0)
R
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.

Roorback answered 10/11, 2009 at 17:28 Comment(0)
N
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.

Nonpareil answered 30/3, 2019 at 8:18 Comment(0)
M
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);
Morehouse answered 10/11, 2009 at 17:1 Comment(4)
sb = new StringBuilder() IS making a new string builder object.Schopenhauerism
Doing that DOES make a new string builder object altogether.Fremont
I think Matt means declare a new variable FOR the new StringBuilder.Cowey
Sorry, to clairify I'm recommending doing something like this: var wellNamedStringBuilder = new StringBuilder();Morehouse
L
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

Lail answered 8/3, 2018 at 2:2 Comment(0)
P
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;
}
Petty answered 24/8, 2018 at 18:11 Comment(0)
G
0

I created some Extension Methods for StringBuilder that complement the built in Clear feature that was added in .NET 4.0

This will clear the StringBuilder and reset the Capacity depending on which one you choose.

sb.Clear(); // Normal Clear
sb.Clear64(); // Reset Capacity to 64
sb.Clear128(); // Reset Capacity to 128
sb.Clear256(); // Reset Capacity to 256

This is faster than creating a new StringBuilder every time, especially for smaller strings.

Extension Methods

/// <summary>
/// Clear the <see cref="StringBuilder"/> and reset the <see href="Capacity"/> to <see href="64"/>
/// </summary>
/// <param name="sb">string builder</param>
public static void Clear64(this StringBuilder sb)
{
    sb.Length = 0;

    if (sb.Capacity > 64)
    {
        sb.Capacity = 64;
    }
}

/// <summary>
/// Clear the <see cref="StringBuilder"/> and reset the <see href="Capacity"/> to <see href="128"/>
/// </summary>
/// <param name="sb">string builder</param>
public static void Clear128(this StringBuilder sb)
{
    sb.Length = 0;

    if (sb.Capacity > 128)
    {
        sb.Capacity = 128;
    }
}

/// <summary>
/// Clear the <see cref="StringBuilder"/> and reset the <see href="Capacity"/> to <see href="256"/>
/// </summary>
/// <param name="sb">string builder</param>
public static void Clear256(this StringBuilder sb)
{
    sb.Length = 0;

    if (sb.Capacity > 256)
    {
        sb.Capacity = 256;
    }
}
Gastroenterology answered 6/5 at 7:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.