6

I have a StringBuilder object where I am adding some strings like follows:

I want to know which one is better approach here, first one is this:

StringBuilder sb = new StringBuilder();
sb.Append("Hello" + "How" + "are" + "you");

and the second one is:

StringBuilder sb = new StringBuilder();
sb.Append("Hello").Append("How").Append("are").Append("you");
Embedd_0913
  • 16,125
  • 37
  • 97
  • 135
  • 3
    See http://stackoverflow.com/questions/9132338/how-many-string-objects-will-be-created-when-using-a-plus-sign/9132374#9132374. This has been covered *to death* :-) – Chris Shain Aug 13 '12 at 16:04
  • You could find [this analysis](http://www.dotnetperls.com/stringbuilder-performance) interesting – Steve Aug 13 '12 at 16:08
  • My question is - why would you want to do "Hello" + "How" etc, when "HelloHow" would be fine? What's the actual point of the question because my answer got bashed for technical reasons which I don't think is the point here... – Charleh Aug 13 '12 at 16:24

5 Answers5

10

In your current example, the string literals:

"Hello" + "How" + "are" + "you"

Will be compiled into one constant string literal by the compiler, so it is technically faster than:

sb.Append("Hello").Append("How").Append("are").Append("you");

However, were you to use string variables:

sb.Append(s1 + s2 + s3 + s4);

Then the latter would be faster as the former could potentially create a series of strings (because of the concatenation) before passing the final string into the Append method, whereas the latter would avoid the extra string creations (but trades off extra method calls and internal buffer resizing).

Update: For further clarity, in this exact situation where there are only 4 items being concatenated, the compiler will emit a call to String.Concat(string, string, string, string), which knowing the length and number of strings will be more efficient than StringBuilder.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • Yes, you'd get 3 strings created in the evaluation of the expression `s1+s2+s3+s4`: s1+s2 -> t1, t1+s3 -> t2, t2+s2 -> t3. – Nicholas Carey Aug 13 '12 at 16:54
  • @NicholasCarey no, in the evaluation of `s1 + s2 + s3 + s4`, the only new string created is the result. That expression is compiled into a single call to `String.Concat`, which does not allocate any intermediate extra strings. – Chris Shain Aug 14 '12 at 01:18
  • In this instance, as eluded to by the other answers, `String.Concat` may end up being faster (due to internal resizing done by the `StringBuilder`. In a single instance such as this with known quantities, I would favour concatenation. With unknown quantities, such as loops, I would favour `StringBuilder`. – Adam Houldsworth Aug 14 '12 at 05:30
7

The first will be more efficient. The compiler will convert it to the following single call:

StringBuilder sb = new StringBuilder();
sb.Append("HelloHowareyou");

Measuring the performance

The best way to know which is faster is to measure it. I'll get straight to the point: here are the results (smaller times means faster):

sb.Append("Hello" + "How" + "are" + "you")                  : 11.428s
sb.Append("Hello").Append("How").Append("are").Append("you"): 15.314s
sb.Append(a + b + c + d)                                    : 21.970s
sb.Append(a).Append(b).Append(c).Append(d)                  : 15.529s

The number given is the number of seconds to perform the operation 100 million times in a tight loop.

Conclusions

  • The fastest is using string literals and +.
  • But if you have variables, using Append is faster than +. The first version is slower because of an extra call to String.Concat.

In case you want to test this yourself, here's the program I used to get the above timings:

using System;
using System.Text;

public class Program
{
    public static void Main()
    {
        DateTime start, end;
        int numberOfIterations = 100000000;
        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Hello" + "How" + "are" + "you");
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(\"Hello\" + \"How\" + \"are\" + \"you\")", start, end);

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Hello").Append("How").Append("are").Append("you");
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(\"Hello\").Append(\"How\").Append(\"are\").Append(\"you\")", start, end);

        string a = "Hello";
        string b = "How";
        string c = "are";
        string d = "you";

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(a + b + c + d);
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(a + b + c + d)", start, end);

        start = DateTime.UtcNow;
        for (int i = 0; i < numberOfIterations; ++i)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(a).Append(b).Append(c).Append(d);
        }
        end = DateTime.UtcNow;
        DisplayResult("sb.Append(a).Append(b).Append(c).Append(d)", start, end);

        Console.ReadLine();
    }

    private static void DisplayResult(string name, DateTime start, DateTime end)
    {
        Console.WriteLine("{0,-60}: {1,6:0.000}s", name, (end - start).TotalSeconds);
    }
}
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
4

String constants will be concatenated at compile time by the compiler. If you are concatenating no more than four string expressions, the compiler will emit a call to String.Concat

s + t + u + v ==> String.Concat(s, t, u, v)

This performs faster than StringBuilder, as StringBuilder might have to resize its internal buffer, while Concat can calculate the total resulting length in advance. If you know the maximum length of the resulting string in advance, however, you can initialize the StringBuilder by specifying an initial working buffer size

var sb = new StringBuilder(initialBufferSize);

StringBuilder is often used in a loop and other dynamic scenarios and performs faster than s += t in such cases.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

In the first case the compiler will construct a single string, so you'll only call Append once. However, I doubt this will make much of a difference. What did your measurements show?

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
-3

The second one is the better approach. Strings are immutable meaning that when you use sb.Append("Hello" + "How" + "Are" + "You") you are creating multiple copies of the string

e.g.

"Hello"

then

"HelloHow"

then

"HelloHowAre"

etc.

The second piece of code is much more performant

edit: Of course this doesn't take into consideration compiler optimisations, but it's best to use the class as intended

Ok as people have pointed out since these are literals the compiler takes care of optimising these operations away - but my point is that doing string concatenation is something that StringBuilder tries to avoid

For instance, looping several times as such:

var someString = "";

foreach (var s in someListOfStrings) 
{
    someString += s;
}

Is not as good as doing:

var sb = new StringBuilder();

foreach(var s in someListOfStrings)
{
    sb.Append(s);
}

sb.ToString();

As this will likely be much quicker since, as I said before, strings are immutable

I assumed the OP was talking about using concatenation in general since

sb.Append("Hello" + "How");

Seems completely pointless when

sb.Append("HelloHow");

Would be more logical...?

It seems to me that in the OPs mind, the placeholder text would eventually become a shedload of variables...

Charleh
  • 13,749
  • 3
  • 37
  • 57
  • 1
    You aren't actually doing this - the compiler maps this to a single String.Concat call. – Reed Copsey Aug 13 '12 at 16:05
  • 1
    `"Hello" + "How" + "Are" + "You"` are string `literals` though – dtsg Aug 13 '12 at 16:06
  • @john not after the compiler gets through with them. If the code is actually written that way, the compiler folds them into a single string literal. – Chris Shain Aug 13 '12 at 16:07
  • Isn't the point of SO to make people better programmers? I'd say that the second approach is the intended use of StringBuilder, and that whilst technically correct, it's misleading to think that string + string + string is a *better* approach since this could lead to someone using a lot of string concatenation - something that StringBuilder attempts to circumvent... – Charleh Aug 13 '12 at 16:09
  • 1
    @ChrisShain Yes, that's what I was getting at. – dtsg Aug 13 '12 at 16:09
  • @Charleh You need to recognize the difference between concatenating string *variables* and string *literals*. From a performance standpoint, the two are entirely different. One is done at compile time, the other at run time. – Servy Aug 13 '12 at 16:10
  • I recognise the difference between literals and variables, but what's to say that someone else doesn't? – Charleh Aug 13 '12 at 16:11
  • 1
    @Charleh You should explain the difference, since it's particularly relevant to this question, as the other (better) answers have. – Servy Aug 13 '12 at 16:13