11

Possible Duplicate:
Why is String.Concat not optimized to StringBuilder.Append?

One day I was ranting about a particular Telerik control to a friend of mine. I told him that it took several seconds to generate a controls tree, and after profiling I found out that it is using a string concatenation in a loop instead of a StringBuilder. After rewriting it worked almost instantaneously.

So my friend heard that and seemed to be surprised that the C# compiler didn't do that conversion automatically like the Java compiler does. Reading many of Eric Lippert's answers I realize that this feature didn't make it because it wasn't deemed worthy enough. But if, hypothetically, costs were small to implement it, what rationale would stop one from doing it?

Community
  • 1
  • 1
Roman Royter
  • 1,655
  • 13
  • 28
  • 2
    There's nothing technically stopping you from performing this optimization, but consider that the two operations are not semantically equivalent. Concatenating a `string` returns a new `string` object that is the result of the operation, while using `StringBuilder` will modify the existing string object. Code analysis would have to be performed to ensure that you were not in any way relying on side effects of the concatenation. In most cases you're not so this not a problem that is impossible to overcome, but then again, it's not really that hard to write the code correctly in the first place. – Cody Gray - on strike Feb 03 '12 at 05:46
  • 1
    See also http://blogs.msdn.com/b/ericlippert/archive/2011/07/19/strings-immutability-and-persistence.aspx – SLaks Feb 03 '12 at 05:49
  • 1
    have look to this post also : http://pranayamr.blogspot.com/2011/02/why-to-user-stringbuilder-over-string.html – Pranay Rana Feb 03 '12 at 05:52

2 Answers2

10

But if, hypothetically, costs were small to implement it, what rationale would stop one from doing it?

It sounds like you're proposing a bit of a tautology: if there is no reason to not do X, then is there a reason to not do X? No.

I see little value in knowing the answers to hypothetical, counterfactual questions. Perhaps a better question to ask would be a question about the real world:

Are there programming languages that use this optimization?

Yes. In JScript.NET, we detect string concatenations in loops and the compiler turns them into calls to a string builder.

That might then be followed up with:

What are some of the differences between JScript .NET and C# that justify the optimization in the one language but not in the other?

A core assumption of JScript.NET is that its programmers are mostly going to be JavaScript programmers, and many of them will have already built libraries that must run in any implementation of ECMAScript. Those programmers might not know the .NET framework well, and even if they do, they might not be able to use StringBuilder without making their library code non-portable. It is also reasonable to assume that JavaScript programmers may be either novice programmers, or programmers who came to programming via their line of business rather than a course of study in computer science.

C# programmers are far more likely to know the .NET framework well, to write libraries that work with the framework, and to be experienced programmers who understand why looped string concatenation is O(n2) in the naive implementation. They need this optimization generated by the compiler less because they can just do it themselves if they deem it necessary.

In short: compiler features are about spending our budget to add value for the customer; you get more "bang for buck" adding the feature to JScript.NET than you do adding it to C#.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • thanks for answering. I haven't proposed a tautology however. Sometimes features do not get added for ideological reasons, not just pure costs (to design, implement, test). For example, you have stated yourself, that C# doesn't include a .ForEach extension simply because it will introduce unnecessary ambiguity. Costs to add this oneliner are miniscule, and yet the rationale is unrelated to them. But I think your final conclusion is a satisfactory argument for me to use with my friend. – Roman Royter Feb 03 '12 at 16:50
  • @RomanR.: I'm skeptical of that. Can you offer an example of an ideological decision that does not in truth also constitute a cost-based decision? – Brian Feb 03 '12 at 17:24
  • @Brian: RomanR's example is a good one; we could do a ForEach extension method on `IEnumerable` for very low cost, and some benefit but to my mind, it does not fit in with the "spirit" of LINQ, which is to avoid side effects. That's "points against" doing the feature. There is also of course a budgetary argument against doing it, namely the opportunity cost of not doing a better feature. But points against are points against, and not all points against are cost based. – Eric Lippert Feb 03 '12 at 17:35
  • Personally dislike the `Foreach` extension method for similar reasons as you. But the problem with leaving it out of the framework is that we now get many subtly different third party versions of it, because many people think it is a good idea. So I believe the current situation is worse than including it in the framework. – CodesInChaos Feb 03 '12 at 19:15
  • Looks like Java 8 compiler does perform this optimization: https://dzone.com/articles/string-concatenation-performacne-improvement-in-ja – vkelman Dec 23 '16 at 18:56
7

The C# compiler does better than that.

a + b + c is compiled to String.Concat(a, b, c), which is faster than StringBuilder.
"a" + "b" is compiled directly to "ab" (useful for multi-line literals).

The only place to use StringBuilder is when concatenating repetitively inside a loop; the compiler cannot easily optimize that.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Is it really faster irrespective of the size and number of the strings being concatenated? – Shredderroy Feb 03 '12 at 05:46
  • 4
    That's *exactly* what the question is talking about, though: concatenating in a loop. – Cody Gray - on strike Feb 03 '12 at 05:46
  • 1
    @CodyGray: I find it hard to believe that Java optimizes that. – SLaks Feb 03 '12 at 05:49
  • 1
    @Shredderroy: Yes. `Concat` knows the size in advance, so it never needs to re-allocate. I don't know how it would compare to a pre-sized `StringBuilder`; I would guess that `Concat` would be minutely faster. – SLaks Feb 03 '12 at 05:50
  • 2
    The compiler *can* easily optimize that; it's not a difficult optimization to write. We just choose not to. – Eric Lippert Feb 03 '12 at 16:25