Let\'s say that you want to output or concat strings. Which of the following styles do you prefer?
var p = new { FirstName = \"Bill\", LastName = \"Ga
I prefer the second as well but I have no rational arguments at this time to support that position.
I choose based on readability. I prefer the format option when there's some text around the variables. In this example:
Console.WriteLine("User {0} accessed {1} on {2}.",
user.Name, fileName, timestamp);
you understand the meaning even without variable names, whereas the concat is cluttered with quotes and + signs and confuses my eyes:
Console.WriteLine("User " + user.Name + " accessed " + fileName +
" on " + timestamp + ".");
(I borrowed Mike's example because I like it)
If the format string doesn't mean much without variable names, I have to use concat:
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
The format option makes me read the variable names and map them to the corresponding numbers. The concat option doesn't require that. I'm still confused by the quotes and + signs, but the alternative is worse. Ruby?
Console.WriteLine(p.FirstName + " " + p.LastName);
Performance wise, I expect the format option to be slower then the concat, since format requires the string to be parsed. I don't remember having to optimize this kind of instruction, but if I did, I'd look at string
methods like Concat()
and Join()
.
The other advantage with format is that the format string can be put in a configuration file. Very handy with error messages and UI text.
Here are my results over 100,000 iterations:
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took (avg): 0ms - 689 ticks
Console.WriteLine(p.FirstName + " " + p.LastName); took (avg): 0ms - 683 ticks
And here is the bench code:
Stopwatch s = new Stopwatch();
var p = new { FirstName = "Bill", LastName = "Gates" };
//First print to remove the initial cost
Console.WriteLine(p.FirstName + " " + p.LastName);
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
int n = 100000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;
for (var i = 0; i < n; i++)
{
s.Start();
Console.WriteLine(p.FirstName + " " + p.LastName);
s.Stop();
cElapsedMilliseconds += s.ElapsedMilliseconds;
cElapsedTicks += s.ElapsedTicks;
s.Reset();
s.Start();
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
s.Stop();
fElapsedMilliseconds += s.ElapsedMilliseconds;
fElapsedTicks += s.ElapsedTicks;
s.Reset();
}
Console.Clear();
Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took (avg): " + (fElapsedMilliseconds / n) + "ms - " + (fElapsedTicks / n) + " ticks");
Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took (avg): " + (cElapsedMilliseconds / n) + "ms - " + (cElapsedTicks / n) + " ticks");
So, I don't know whose reply to mark as an answer :)
Generally I prefer the former, as especially when the strings get long it can be much easier to read.
The other benefit is I believe one of performance, as the latter actually performs 2 string creation statements before passing the final string to the Console.Write method. String.Format uses a StringBuilder under the covers I believe, so multiple concatenations are avoided.
It should be noted however that if the parameters you are passing in to String.Format (and other such methods like Console.Write) are value types then they will be boxed before passed in, which can provide its own performance hits. Blog post on this here.
Starting from C# 6.0 interpolated strings can be used to do this, which simplifies the format even more.
var name = "Bill";
var surname = "Gates";
MessageBox.Show($"Welcome to the show, {name} {surname}!");
An interpolated string expression looks like a template string that contains expressions. An interpolated string expression creates a string by replacing the contained expressions with the ToString represenations of the expressions’ results.
Interpolated strings have similar performance to String.Format, but improved readability and shorter syntax, due to the fact that values and expressions are inserted in-line.
Please also refer to this dotnetperls article on string interpolation.
If you are looking for a default way to format your strings, this makes sense in terms of readability and performance (except if microseconds is going to make a difference in your specific use case).