1

Update

Please see this question: Does StringBuilder use more memory than String concatenation?. I believe Dan Taos' answers my question. I wanted to make sure that his answer is still sound as it is dated 2010? I believe this also answers my question: https://coders-corner.net/2014/08/20/concatenate-strings-in-c-operator-vs-string-concat-vs-stringbuilder/

Original Question

This approach is frowned upon using C#:

public string getMessage()
{
    string message = "Hello";
    string message += " my";
    string message += " name";
    string message += " is";
    string message += " bert";
    return message;
}

This is better:

public string getMessage()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("Hello");
    sb.Append(" my");
    sb.Append(" name");
    sb.Append(" is");
    sb.Append(" Bert");
    return message.ToString();
}

How does this approach compare to the second approach:

public string getMessage()
{
    return string.Concat("Hello",  " my", " name", " is", " Bert");
}

I like the third approach because it is only one line of code. Are there any implications of using the third approach? I have looked at the .NET reference here: https://referencesource.microsoft.com/#mscorlib/system/string.cs,8281103e6f23cb5c and specifically the method with signature: public static String Concat(params String[] values). However, I still wanted to confirm?

w0051977
  • 15,099
  • 32
  • 152
  • 329
  • 1
    you missed `return "Hello"+" my"+" name"+" is"+" Bert";` which equals the first approach in one line – fubo Feb 14 '18 at 10:42
  • 1
    This might help you https://stackoverflow.com/a/11133227/6306281 – Michael Hancock Feb 14 '18 at 10:42
  • 2
    Relevant: https://ericlippert.com/2012/12/17/performance-rant/ – DavidG Feb 14 '18 at 10:44
  • 2
    None of these approaches are materially different in terms of performance unless `getMessage` is called many, many times, because you're concatenating a constant amount of strings. Using `StringBuilder` starts making a big difference when you don't know the strings you're concatenating in advance, and in such scenarios, using `Concat` is usually not possible or practical. If you do know exactly what string you want already, consider using a verbatim string (@"") or just plain `+`, so the compiler can take care of things for you with no overhead. – Jeroen Mostert Feb 14 '18 at 10:52
  • 1
    Please be specific in your question here. Are you asking only about the given examples as shown, or are you asking in the general sense? I ask because minor adjustments to the number of string parts to your code will drastically change the "which is fastest" answer, which means that the only really general answer that can be given to such a broad question is "it depends". – Lasse V. Karlsen Feb 14 '18 at 10:57
  • 1
    @fubo: Not true. The compiler will treat that as `return "Hello my name is Bert";`. If they were all variables then it would put them in an array and call `String.Concat` on the array whereas the original calls `String.Concat` once for each line. So in fact your approach is actually equivalent to the third approach. – Chris Feb 14 '18 at 11:23
  • Please see this question: https://stackoverflow.com/questions/4191079/does-stringbuilder-use-more-memory-than-string-concatenation. I believe Dan Taos' answers my question. I wanted to make sure that his answer is still sound as it is dated 2010? – w0051977 Feb 14 '18 at 11:42
  • Please make sure your example code compiles. The first snippet does not. – Chris Dunaway Feb 14 '18 at 19:18

2 Answers2

1

This depends on what you want. If you are contatenating 2 string than I suppose this will be faster than StringBuilder as there is a certain overhead in instantiating StringBuilder class. If, on the other hand, you are contatenating 100 strings than StringBuilder class will be much faster. The reason why it is faster is that it uses a buffer rather than normal string contatenation(string is immutable).

string.Concat() does not use StringBuilder internally so this assumption is wrong.

Try to look at the string.Concat overload and you might get a better idea when to use string.Concat and when to use StringBuilder. You will notice that there are couple of overloads(10 to be exact but lets look at these 5).

string.Concat(arg0)
string.Concat(arg0, arg1)
string.Concat(arg0, arg1, arg2)
string.Concat(arg0, arg1, arg2, arg3)
string.Concat(params string[])

If you make a benchmark where you use all these methods along with StringBuilder you will notice that somewhere around 4 string contatenations StringBuilder will take the lead. This is because first 4 string.Concat() methods are more optimized than the last one that simply takes how many arguments as is needed.

Interesting enough, if you would add another measuring series but this time for StringBuilder where you instantiate it with capacity than that StringBuilder would take the lead since there is an overhead when StringBuilder reaches it's current capacity ceiling.

EDIT: I have found my benchmark results(this was for a dissertation in 2011). This was done 100,000 times for reliability purposes. Axis X is number of string used in contatenation and axis Y is the duration.

enter image description here

Robert
  • 2,407
  • 1
  • 24
  • 35
  • Does the third option create five separate strings (like the first option)? – w0051977 Feb 14 '18 at 11:28
  • I don't understand you question. – Robert Feb 14 '18 at 11:29
  • The first fragment of code creates five strings in memory. The third approach only creates one string in memory (after tostring is called).. – w0051977 Feb 14 '18 at 11:35
  • I do not know on which fragments you are refering. I simply listed 5 methods in a row. – Robert Feb 14 '18 at 11:38
  • Please see this question: https://stackoverflow.com/questions/4191079/does-stringbuilder-use-more-memory-than-string-concatenation. I believe Dan Taos' answers my question. I wanted to make sure that his answer is still sound as it is dated 2010. – w0051977 Feb 14 '18 at 11:39
  • I see...Yes the string.Concat will allocate new string each time it contatenates. If you are contatenating 2 strings "Tom" and "Jerry" you are basically(just as it is explained in the answer of the question you linked) allocating a new char array with size of both strings and than copying both of those strings inside. The last option that takes params string[] as a parameter is the worst as new allocation needs to be done for each contatenation. – Robert Feb 14 '18 at 11:45
  • If I am only concatenating two strings, then I guess string.concat is better than stringbuilder? – w0051977 Feb 14 '18 at 11:47
  • You are absolutely right! One more thing to note in the article you linked in the question edit you just did. The article author lays out information in a way that one could assume that '+' and string.Concat are different when they are actually the same. If you call string1 + string2, it is the same as if you wrote string1.Concat(string2) or string.Concat(string1, string2). The compailer will translate '+' operator to method call which is in our case string.Concat(). – Robert Feb 14 '18 at 11:50
  • I just realized that you were reffering to the fragments in the question itself(sorry, wasn't paying atention). Third fragment will create 5 separate strings in the memory same as the first fragment because the overload that takes params string[] is called and that overload is not optimized like the first 4 are. – Robert Feb 14 '18 at 11:54
  • What if I only create two strings? – w0051977 Feb 14 '18 at 12:02
  • Contatenating 2, 3 or 4 strings is faster with string.Concat than it is with StringBuilder. – Robert Feb 14 '18 at 12:05
  • But it really makes no sense to use `StringBuilder` just to concatenate 2, 3 or 4 strings. The time savings over the normal concatenate operator is likely negligible. – Chris Dunaway Feb 14 '18 at 19:22
  • @ChrisDunaway I agree. This is the conclusion of the answer if you read carefully. To be honest I would use string.Concat always unless I am repeating the operation many, many times. In my career I had maybe 2-3 cases where using StringBuilder really payed off. – Robert Feb 14 '18 at 20:00
0

StringBuilder is so much optimized. It's my test:

static void ConcatenateWithOperator()
{
    string txt = string.Empty;

    for (int i = 0; i < 1000; i++)
    {
        txt += new string('x', i);
    }
}

static void ConcatenateWithStringBuilder()
{
    StringBuilder builder = new StringBuilder();

    for (int i = 0; i < 1000; i++)
    {
        builder.Append(new string('x', i));
    }

    string result = builder.ToString();
}

static void ConcatenateWithConcat()
{
    string txt = string.Empty;

    for (int i = 0; i < 1000; i++)
    {
        txt = string.Concat(txt, new string('x', i));
    }
}

static void ConcatenateWithOperator2()
{
    for (int i = 0; i < 1000; i++)
    {
        string result = new string('x', i) + new string('x', i);
    }
}

static void ConcatenateWithStringBuilder2()
{
    for (int i = 0; i < 1000; i++)
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(new string('x', i));
        builder.Append(new string('x', i));
        string result = builder.ToString();
    }
}

    DateTime start1 = DateTime.Now;
    ConcatenateWithOperator();
    Console.WriteLine((DateTime.Now - start1).TotalSeconds);

    DateTime start2 = DateTime.Now;
    ConcatenateWithStringBuilder();
    Console.WriteLine((DateTime.Now - start2).TotalSeconds);

    DateTime start3 = DateTime.Now;
    ConcatenateWithConcat();
    Console.WriteLine((DateTime.Now - start3).TotalSeconds);

    DateTime start4 = DateTime.Now;
    ConcatenateWithOperator2();
    Console.WriteLine((DateTime.Now - start4).TotalSeconds);

    DateTime start5 = DateTime.Now;
    ConcatenateWithStringBuilder2();
    Console.WriteLine((DateTime.Now - start5).TotalSeconds);

And the results:

0,3087516  // many strings concatenated with + operator
0,0030022  // many strings concatenated with StringBuilder
0,1941643  // many strings concatenated with Concat
0,0040039  // two strings concatenated with + operator
0,004003   // two strings concatenated with StringBuilder

So, the + operator is efficient as StringBuilder only if you want to concatenate small amount of strings.

fdafadf
  • 809
  • 5
  • 13
  • Please see this question: https://stackoverflow.com/questions/4191079/does-stringbuilder-use-more-memory-than-string-concatenation. I believe Dan Taos' answers my question. I wanted to make sure that his answer is still sound as it is dated 2010. – w0051977 Feb 14 '18 at 11:40