Razer
Razer

Reputation: 8201

Performance creating concatenated strings

Which way to create strings is more run time efficient in C#

Number 1:

bool value = true;
int channel = 1;
String s = String.Format(":Channel{0}:Display {1}", channel, value ? "ON" : "OFF");

Number 2:

bool value = true;
String channel = "1";
string  s = ":Channel" + channel + ":Display " + value ? "ON" : "OFF";

Upvotes: 7

Views: 1338

Answers (4)

Adam C
Adam C

Reputation: 20

Regarding Marc Gravell's answer: You can avoid the boxing operation by passing channel.ToString(). I have verified emperically that this gives a slight performance improvement for both #1 and #2.

  • In case #1, you avoid the boxing operation.
  • In case #2, you avoid calling the implicit conversion operator.

But after trying to disprove your theory, (with longer concatenations and random strings) I must concede that #2 is faster than #1.

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062502

I'm going to add an example now to illustrate how the compiler treats the two, because there seems to be a lot of confusion in some of the other answers (edit: note that much of these confusions have now been deleted/edited away):

bool value = true;
int channel = 1;
String s = String.Format(":Channel{0}:Display {1}", channel,
    value ? "ON" : "OFF");

The last line is compiled as:

String s = String.Format(":Channel{0}:Display {1}",
    new object[2] {(object)channel, value ? "ON" : "OFF")};

note interestingly the creation of an array and a "box" for int channel, and of course the extra parsing required to find {0} / {1}.

Now Number 2:

bool value = true;
String channel = "1";
string  s = ":Channel" + channel + ":Display " + (value ? "ON" : "OFF");

The last line is compiled as:

string s = string.Concat(":Channel", channel, ":Display ", value ? "ON" : "OFF");

here there is no array, no box (channel is now a string), and no parsing. The overload is public static string string.Concat(string,string,string,string); string.Concat is implemented very efficiently, pre-allocating a right-sized string in advance then over-writing, etc.

In most code, either is fine. The second version is technically more efficient (no box, no array, no parsing), but is a major pain if you ever want to internationalize later. In most applications you will not notice any difference between the two. The parsing is fast, and the box / array are collected cheaply as gen-zero objects. But cheap is not free.

Upvotes: 7

Claudio Redi
Claudio Redi

Reputation: 68400

This could help you to test this yourself. This was executed using .net v4.0.30319 runtime.

sw = new System.Diagnostics.Stopwatch();

// Number 1
bool value = true;
int channel = 1;
sw.Start();
for (int i = 0; i <= 100000; i++)
{
    String s = String.Format(":Channel{0}:Display {1}", channel, value ? "ON" : "OFF");
}
sw.Stop();

sw.Reset();

// Number 2
sw.Start();
for (int i = 0; i <= 100000; i++)
{
    string s = "Channel" + channel + ":Display " + (value ? "ON" : "OFF");
}
sw.Stop();

My result is:

Number 1: 136ms

Number 2: 91ms

So the second option has better performance. The fact that the first option uses an extra method call (string.Format()) and replacing parameters (as Marc remarked) is what makes the difference.

If instead of using 100.000 iterations I use 1.000.000, this is what I get

Number 1: 1308ms

Number 2: 923ms

Basically, same conclusion.

Upvotes: 6

Georgii Gonchar
Georgii Gonchar

Reputation: 446

Number 1 is the most efficient.

String.Format() function uses System.Text.StringBuilder type internally for concatenating strings.

The StringBuilder is used to represent a mutable(aka editable) strings and it is the most efficient way to concatinate strings. http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx.

Upvotes: -4

Related Questions