String concatenation -- not the typical question

J

Justin M. Keyes

Hi,

Please read carefully before assuming that this is the same old
question about string concatenation in C#!

It is well-known that the following concatenation produces multiple
immutable String objects for each statement:

String a = "a";
a += "b";
a += "c";
a += "d";

However, I have not seen any source say whether or not the following
statement creates a new String object for each concatenation (i.e.,
each "+" sign):

String b = a + "b" + "c" + "d";

In other words: if the concatenation is done all in one statement, does
the compiler optimize the assignment to b? If the assignment to b had,
say, twenty such concatenations in it, would there be a reason to use
StringBuilder?

Thanks very much.

Justin
 
J

Justin M. Keyes

Two more questions:
What if the terms of the assignment to b were all string literals?
What if the terms of the assignment to b were all string variables?

Thanks!
Justin
 
B

Bill Butler

However, I have not seen any source say whether or not the following
statement creates a new String object for each concatenation (i.e.,
each "+" sign):

String b = a + "b" + "c" + "d";

This statement in simply converted into concatenation behind the scenes.
<Unverified>
It is also possible that it will optimize away the concatenation of literals altogether.
In other words: if the concatenation is done all in one statement, does
the compiler optimize the assignment to b?
Yes

If the assignment to b had,
say, twenty such concatenations in it, would there be a reason to use
StringBuilder?

If you are using + as opposed to += you are fine doing it this way
 
J

Justin M. Keyes

Thanks for your help. For literals I certainly agree, but what if the
statement uses variables? E.G., my statement above has the variable 'a'
as a term.
 
A

Andrew Robinson

The compiler is typically pretty smart about these things. Take a look at
your code using reflector:

static void Main(string[] args)
{
string a = "A" + "B" + "C" + "D" + "E" + "F" + "G";
Console.WriteLine(a);
}

private static void Main(string[] args)
{
string text1 = "ABCDEFG";
Console.WriteLine(text1);
}

but it not smarter than your application:

static void Main(string[] args)
{
string a = "A";
string b = "B";
string c = "C";
string d = a + b + c;
Console.WriteLine(a);
}

private static void Main(string[] args)
{
string text1 = "A";
string text2 = "B";
string text3 = "C";
string text4 = text1 + text2 + text3;
Console.WriteLine(text1);
}


and now for a slightly different question and answer:

static void Main(string[] args)
{
string a = "A" + "B" + "C" + "D" + "E" + "F" + "G";
string b = "ABCDEFG";
}

take a look at the debug disassembly and you will see that both a and b are
initialized with the same literal:

string a = "A" + "B" + "C" + "D" + "E" + "F" + "G";
00000029 mov eax,dword ptr ds:[0227307Ch]
0000002f mov edi,eax
string b = "ABCDEFG";
00000031 mov eax,dword ptr ds:[0227307Ch]
00000037 mov esi,eax
 
J

Jon Skeet [C# MVP]

Bill Butler said:
This statement in simply converted into concatenation behind the scenes.
<Unverified>
It is also possible that it will optimize away the concatenation of
literals altogether.
</Unverified>

Not just possible - guaranteed. Whenever there is a constant expression
(as per the spec definition of "constant expression") the expression is
evaluated at compile-time.
 
J

Jon Skeet [C# MVP]

Justin M. Keyes said:
Thanks for your help. For literals I certainly agree, but what if the
statement uses variables? E.G., my statement above has the variable 'a'
as a term.

It ends up as a single concatenation: a+"bcd". That's as fast as (or
faster than) using a StringBuilder.
 
B

Bill Butler

Jon Skeet said:
Not just possible - guaranteed. Whenever there is a constant expression
(as per the spec definition of "constant expression") the expression is
evaluated at compile-time.

Thanks Jon,

I wasn't ABSOLUTLY sure so I waffled.
 
B

Bruce Wood

I'm surprised that Jon didn't point you to his page on StringBuilder :)
Here it is.

http://www.yoda.arachsys.com/csharp/stringbuilder.html

The answer is that if the statement uses variables, it is compiled into
a single call to String.Concat(), which does not create intermediate
copies of the string. You get multiple intermediate copies only if you
write this:

string a = b;
a += c;
a += d;
a += e;
....
 
J

Justin M. Keyes

That is *exactly* what I was looking for.

Bruce Wood, Andrew Robinson, Bill Butler, and Jon Skeet, thanks very
much!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top