How to make StringBuilder empty again in .NET 3.5 ?
Asked Answered
A

7

20

I have a loop where i create some string value based on certain conditions. I did place StringBuilder object outside of the loop and each time i have new row in loop i need to clear StringBuilder appended values for this row.

How do i clear those?

        StringBuilder sb = new StringBuilder();

        foreach (DataRow row in recipientsList.Rows)
        {
            sb.Length = 0;
            sb.Append("<ul>");
            if (row["needsToActivate"] == "1")
            {
                sb.AppendFormat("<li>{0}</li>", getUsersWithoutActivationTemplate());
            }
            if (row["needsToEnterSite"] == "1")
            {
                sb.AppendFormat("<li>{0}</li>", getUsersWithoutEnteringWebsiteForTwoWeeksTemplate());
            }
            if (row["needsPicture"] == "1")
            {
                sb.AppendFormat("<li>{0}</li>", getUsersWithoutPicturesTemplate());
            }
            if (row["needsText"] == "1")
            {
                sb.AppendFormat("<li>{0}</li>", getUsersWithoutTextTemplate());
            }
            if (row["needsCharacteristic"] == "1")
            {
                sb.AppendFormat("<li>{0}</li>", getUsersWithoutCharateristicsTemplate());
            }
            if (row["needsHobby"] == "1")
            {
                sb.AppendFormat("<li>{0}</li>", getUsersWithoutHobbiesTemplate());
            }
            sb.Append("</ul>");
}

Code with accepted answer;

Anglin answered 12/7, 2010 at 9:30 Comment(2)
When do you want to do the clearing during the loop or after it has finished ?Thanhthank
can you show some code, it looks like you only want to keep the latest value.Sideman
E
54

You can simply;

sb.Length = 0;
Eustache answered 12/7, 2010 at 9:32 Comment(4)
exactly what i needed. I did almost use sb.Remove() which complicates the issue.Anglin
you can use this : sb.Remove(0, sb.Length);Alexio
It is not the best idea when you are working with very long strings. It can cause OOM exception. More explanation is provided on MSDN: social.msdn.microsoft.com/Forums/en-US/…Phatic
It is correct to set Length=0 to empty a StringBuilder but keeping its memory. But when using StringBuilder.Insert(), this will not work. The Insert() will add more memory to the Stringbuilder, even if there is plenty of free memory in the StringBuilder. If the StringBuilder is repeatedly inserted and cleared, one gets an Out Of Memory exception finally. See my post: #29574969Bolten
B
13

StringBuilder.Clear(); is what you want.

Book answered 12/7, 2010 at 9:31 Comment(1)
This is only available in .Net 4. .Net <= 3.5 needs to use sb.Length = 0;Alamein
S
4

Set Length to 0, or in .Net 4 I believe you can call the new Clear() method.

Subchloride answered 12/7, 2010 at 9:32 Comment(0)
I
3

Assuming you define your StringBuilder like this: StringBuilder sb = new StringBuilder();

You can do any of the following:

Call the Clear method:

for (int i = 0; i < 100; i++)
{
    sb.Clear();
    .. your code here ..
}

Set the length to zero:

for (int i = 0; i < 100; i++)
{
    sb.Length = 0;
    .. your code here ..
}

Set it to a new object:

for (int i = 0; i < 100; i++)
{
    sb = new StringBuilder();
    .. your code here ..
}
Intercolumniation answered 12/7, 2010 at 9:32 Comment(2)
That last one rather defeats the purpose of using StringBuilder in the first place...Alamein
@codekaizer: No, that last one is probably just as efficient as re-using the thing. The real use of the SB is what happen in the rest of the loop.Contorted
C
3

You can re-use a StringBuilder (with .Clear() or .Length = 0) but if you really want to optimize you should try to estimate the final length. If this grows a little each iteration, re-using could be slower (use more mem) than creating a new one each time.

foreach (DataRow row in recipientsList.Rows)
{
    int estimatedLength = 5000; // maybe a calculation based on row-data
    StringBuilder sb = new StringBuilder(estimatedLength);
    ....

}

So while the answers here about how to do it are correct, the best advice is not to do it . It is a micro-optimization, and you don't need the very small gains here and you don't want the (small) extra complications. You could optimize a little here if the resulting string is very large but certainly don't make this a habit.

Contorted answered 12/7, 2010 at 10:0 Comment(5)
length is eight at max, could be lower. So you're saying that if i assign default length i don't need to sb.Length=0 or it will just create smaller object and reduce time?Anglin
If I look at those AppendFormat() call your length will be a lot greater than eight. But yes, use a good estimate for the expected length and don't try to re-use like this.Contorted
i have 8 Append methods it supposed to be the length or length of largest string appended?Anglin
@eugeneK: No, you need an estimate of the final result, sum of all strings. Round up liberally.Contorted
Thanks will combine your technique with setting length to 0.Anglin
C
0

I faced similar issue.

This trick worked for me

sb.Replace(sb.ToString(), "");

This code will replace entire string with "".

Casaleggio answered 9/7, 2019 at 6:15 Comment(0)
W
0

What I learned is

sb.Length = 0;

But my answer includes a hint on how to use StringBuilder without fragmenting memory. You're being careful to set the length to zero and reuse it, so you're not reallocating it all the time. Why not go a step further, and reduce fragmentation or frequent allocations?

StringBuilder sb = new System.Text.StringBuilder(22_000); // preallocate ~20K

If you can pretty much tell how much space you should need, consider allocating the space the StringBuilder is going to use up-front. There is a reason why the constructor allows you to specify how much space to allocate -- it improves performance. One allocation all-at-once should be faster than lots of little allocations interspersed with others.

So, I'll run some data through the code, look at the StringBuilder size, multiply by some factor, and put that as an initial allocation size for the StringBuilder.

Wellknown answered 12/7, 2019 at 14:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.