7

So...I have this scenario where I have a Foreach loop that loops through a List of Checkboxes to check which are selected. For every selected checkbox, I have to do a pretty long string concatenation, involving 30 different strings of an average length of 20 characters, and then send it out as a HTTP request. 2 of the strings are dependant on the index/value of the checkbox selected.

The length of the List of Checkboxes is also variable depending upon the user's data. I would say the average length of the List would be 20, but it can go up to 50-60. So the worst case scenario would be performing the whole string concatenation 60 or so times.

For now I'm doing it with simple string concatenation via the '+' operator, but I'm wondering if it would be faster to do it with Stringbuilder. Of course, that means I'd have to either create a Stringbuilder object within the loop, or create it before the loop and call Stringbuilder.Remove at the end of it after sending out the HTTP request.

I appreciate any insights anybody can share regarding this issue.

EDIT
Thanks for all the replies everybody, so from what I've gathered, the best way for me to go about doing this would be something like:

 StringBuilder sb = new StringBuilder();
 foreach (CheckBox item in FriendCheckboxList)
 {
     if (item.Checked)
     {
         sb.Append(string1);
         sb.Append(string2);
         sb.Append(string3);
         .
         .
         .
         sb.Append(stringLast);

         SendRequest(sb.ToString());
         sb.Length = 0;
      }
  }
johnnyRose
  • 7,310
  • 17
  • 40
  • 61
Kronon
  • 185
  • 1
  • 2
  • 16
  • I apologize, it seems I do not understand Stringbuilder well enough. So calling Stringbuilder.ToString() clears the Stringbuilder? – Kronon Dec 29 '09 at 05:06
  • No. Setting the Length property to zero clears it. – John Saunders Dec 29 '09 at 05:09
  • someStringBuilder.length = 0; – Stan R. Dec 29 '09 at 05:11
  • I voted your question up, but I also wanted to point out that your edit is misleading. You used the phrase, "the best way" which is A) subjective and B) not correct. Regarding A) Better phrasing would be "the commonly agreed upon way". Regarding B) A "better" way in this case is to use String.Concat instead of StringBuilder, as described in my proposed answer. Nothing wrong with the answer, StringBuilder is fine. Just be careful claiming something as "the best" since often something has been or will be discovered which is actually better. – hemp May 14 '10 at 00:03
  • You could check out this SO post on Concatenation vs Stringbuilder perforamnce. – SwDevMan81 Dec 29 '09 at 05:12

5 Answers5

15

Use StringBuilder. That's what it's for.

Strings are immutable. String concatenation creates a new string, needing more memory, and is generally considered slow:

string a = "John" + " " + "Saunders";

This creates a string "John ", then creates another string "John Saunders", then finally, assigns that to "a". The "John " is left for garbage collection.

string a = "John";
a += " ";
a += "Saunders";

This is about the same, as "John" is replaced by a new string "John ", which is replaced by a new string "John Saunders". The originals are left to be garbage collected.

On the other hand, StringBuilder is designed to be appended, removed, etc.


Example:

StringBuilder sb = new StringBuilder();
for (int i=0; i<n; i++)
{
    sb.Length = 0;
    sb.Append(field1[i]);
    sb.Append(field2[i]);
    ...
    sb.Append(field30[i]);
    // Do something with sb.ToString();
}
Kind Contributor
  • 17,547
  • 6
  • 53
  • 70
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • I apologize if my question seemed frivolous, but I was just wondering if creating a new Stringbuilder object at every loop would lead to unnecessary overhead. – Kronon Dec 29 '09 at 05:01
  • Why would you want to create a new one? – John Saunders Dec 29 '09 at 05:02
  • I would assume that means you're recommending calling Stringbuilder.Remove at the end of every loop then? – Kronon Dec 29 '09 at 05:04
  • John speaks truth - ToString() then clear it, rinse and repeat. – Luke Schafer Dec 29 '09 at 05:04
  • 6
    @John: Does your first example actually create 2 strings? I think rather, that the compiler will optimize that to a single string and that no concatenation will occur. – Chris Dunaway Dec 29 '09 at 14:42
  • @ChrisDunaway: You are correct about Johns example, but he is demonstrating a point which is still relevant for the OP when concatenating in a loop. – Kind Contributor Aug 15 '15 at 05:51
7

This topic has been analysed to death over the years. The end result is that if you are doing a small, known number of concatenations, use '+', otherwise use stringbuilder. From what you've said, concatenate with '+' should be faster. There are a gazillion (give or take) sites out there analysing this - google it.

For the size of string you are talking about, it's negligible anyway.

EDIT: on second thought, SB is probably faster. But like I said, who cares?

Luke Schafer
  • 9,209
  • 2
  • 28
  • 29
  • 2
    I disagree. If he's doing 30 "+" operations, then he's allocating and discarding a lot of strings, while not appending to any of them. – John Saunders Dec 29 '09 at 05:00
  • you got in as I was editing :) I think SB might JUST be faster, but remember that all that 'discarding' of strings is handled by the GC, which does a pretty efficient job of it, and isn't really handled by the current execution path. – Luke Schafer Dec 29 '09 at 05:03
  • its still unnecessary GC work that could be easily avoided...its not like we are talking about 2 or 3 strings... – Stan R. Dec 29 '09 at 05:07
  • There's also the allocation that comes before the discarding... I've seen these concatenations cause visible performance loss. – John Saunders Dec 29 '09 at 05:07
  • As have I, years ago before we used libraries to do all our XML-lovin :) Still, while I can't remember any off the top of my head, There are graphs out there that show that this size of operation shouldn't really be a problem. SB can do some funky things though - I see John that you've updated your post. I would definitely go with your final sample. Still, not really an issue. – Luke Schafer Dec 29 '09 at 05:21
7

I know this has been answered, but I wanted to point out that I actually think the "blindly accepted as gospel" approach of always using StringBuilder is sometimes wrong, and this is one case.

For background, see this blog entry: Link

The short of it is, for this particular case, as described, you will see better performance by avoiding StringBuilder and making use of the + operator thusly:

foreach (CheckBox item in FriendCheckboxList)
{
    if (item.Checked)
    {
        string request = string1 +
            string2 +
            string3 +
            .
            .
            .
           stringLast;
        SendRequest(request);
    }
}

The reason is that the C# compiler (as of .NET 1.1), will convert that statement into a single IL call to String.Concat passing an array of Strings as an argument. The blog entry does an excellent job outlining the implementation details of String.Concat, but suffice to say, it is extremely efficient for this case.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
hemp
  • 5,602
  • 29
  • 43
  • thanks for bringing this up. A lot of people assume they are saving GC calls when they may not be. If it's performance related and it might actually matter then measure it! There are very few "always use X" rules that are right. – Mike Two May 10 '10 at 18:29
  • 1
    When there is a fixed number of strings to concatenate, string.Concat is better by far. All it needs to do is add the total of the string lengths, allocate memory, copy each string, and you're done. If you then expect to do more processing, StringBuilder is probably better. – Kind Contributor Aug 15 '15 at 05:43
1

In general I would recommend to use a StringBuilder.

Have you tested this and checked the performance? Is the performance an issue vs how long it will take you to rewrite the code?

johnnyRose
  • 7,310
  • 17
  • 40
  • 61
Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
  • I'm pretty much done with this project, so now I'm just looking at various ways to optimize my code for better performance. – Kronon Dec 29 '09 at 05:03
1

If your asking this question, chances are you should use StringBuilder for many reasons, but i'll provide two.

  1. When you use string concatenation it has to allocate a new buffer and and copy the data in the other string into the new string variable. So you are going to incur many repeated allocations. Which in the end ends up fragmenting the memory, using up heap space, and making more work for the Garbage collector. The StringBuilder on the other hand pre-allocates a buffer and as you add strings to it doesn't need to keep re-allocating (assuming initial buffer is large enough). Which increases performance and is far less taxing on memory.

  2. As developers we should try to anticipate future growth. Let's say that your list grows substantially over time and then all of a sudden starts performing slowly. If you can prevent this with little effort now, why wouldn't you do it?

James
  • 12,636
  • 12
  • 67
  • 104