7

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";
13
  • 2
    Have you identified this as a performance problem? Pick the more readable one (IMO Format) Commented Mar 10, 2013 at 21:28
  • 2
    @Bart Friederichs: performance issues often have nothing in common. It's often a bad idea to try solving your own performance issues following others' solutions, just because even a tiny difference in the environment may bring a huge difference in results. Commented Mar 10, 2013 at 21:32
  • 1
    No don't have a performance problem. I know preoptimization is the root of all evil. But I'm coming from other hardware where performance is rare. If I implement something new, it doesn't matter if I do it this way or that way - so I can do it right the first time. All changes afterwards sucks... Commented Mar 10, 2013 at 21:38
  • 1
    @DGibbs true; I assume it should be string s = ":Channel" + channel + ":Display " + (value ? "ON" : "OFF"); Commented Mar 10, 2013 at 21:45
  • 1
    The first is far better regardless of its performance: the first technique allows you to isolate the string into a localizable resource. Commented Mar 10, 2013 at 22:26

4 Answers 4

7

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.

Sign up to request clarification or add additional context in comments.

Comments

6

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.

6 Comments

Personally I don't this 16ms vs 12ms is clear cut enough, given timing accuracy
@MarcGravell: Sorry, while you were writing this comment I was adding another example with 100.000 iterations.
That's more like it ;) now all you have to do is run it on the OP's exact .NET (sub-)version, OS (sub-)version, and exact hardware, under exactly the same background load conditions... (ok, I'm teasing now)
@MarcGravell: IMHO the result seems to be pretty conclusive for the same .net runtime. The execution times may change from machine to machine but 2nd option is more efficient (at least from time execution point of view) taking into account the big difference showed on my test.
Indeed; and like I said already - it is much better with those numbers; the 12 vs 16... not very conclusive
|
0

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.

Comments

-4

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.

7 Comments

that reasoning is incomplete; the second version uses string.Concat, which is also heavily optimized. Arguably even more so, since it uses a fast-alloc and overwrite approach, rather than a resized backing buffer. If this was a loop, then sure: StringBuilder would win hands down. For a single-line concat: no; string.Concat is the most appropriate approach, which can be done using the code shown in the 2nd example.
From MSDN Use the String class if you are concatenating a fixed number of String objects. In that case, the compiler may even combine individual concatenation operations into a single operation.
Your edit makes this answer worse and actively incorrect. Sorry, but I don't think you understand how the compiler treats the 2nd example. Hint: it isn't what you describe.
This is the except from Microsoft guide of using string.Concat() : "... when performance is important, you should always use the StringBuilder class to concatenate strings. ..." msdn.microsoft.com/en-us/library/ms228504.aspx
As a general rule of thumb , StringBuilder is only more efficient in cases where you're concatenating very large strings, or very large numbers of strings, perhaps inside of a loop. Something like "Hello" + "World" will boil down to String.Concat which is far better suited to this scenario since we already know the size of the strings before compile time and don't need dynamic resizing that Stringbuilder provides
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.