For a simple case where it's a simple single concatenation, I feel that it's not worth the complexity of string.Format
(and I haven't tested, but I suspect that for a simple case like this, string.Format
might be slightly slower, what with the format string parsing and all). Like Jon Skeet, I prefer to not explicitly call .ToString()
, since that will be done implicitly by the string.Concat(string, object)
overload, and I think the code is cleaner-looking and easier to read without it.
But for more than a few concatenations (how many is subjective), I definitely prefer string.Format
. At a certain point I think that both readability and performance suffer unnecessarily with concatenation.
If there are many parameters to the format string (again, "many" is subjective), I usually prefer to include commented indices on the replacement arguments, lest I lose track of which value goes to which parameter. A contrived example:
Console.WriteLine(
"Dear {0} {1},\n\n" +
"Our records indicate that your {2}, \"{3}\", is due for {4} {5} shots.\n" +
"Please call our office at 1-900-382-5633 to make an appointment.\n\n" +
"Thank you,\n" +
"Eastern Veterinary",
/*0*/client.Title,
/*1*/client.LastName,
/*2*/client.Pet.Animal,
/*3*/client.Pet.Name,
/*4*/client.Pet.Gender == Gender.Male ? "his" : "her",
/*5*/client.Pet.Schedule[0]
);
Update
It occurs to me that the example I've given is a bit confusing, because it appears that I've used both concatenation and string.Format
here. And yes, logically and lexically, that's what I've done. But the concatenations will all be optimized away by the compiler1, since they're all string literals. So at run-time, there will be a single string. So I guess I should say that I prefer to avoid many concatenations at run time.
Of course, most of this topic is out of date now, unless you're still stuck using C# 5 or older. Now we have interpolated strings, which for readability, are far superior to string.Format
, in almost all cases. These days, unless I'm just concatenating a value directly to the beginning or end of a string literal, I almost always use string interpolation. Today, I'd write my earlier example like this:
Console.WriteLine(
$"Dear {client.Title} {client.LastName},\n\n" +
$"Our records indicate that your {client.Pet.Animal}, \"{client.Pet.Name}\", " +
$"is due for {(client.Pet.Gender == Gender.Male ? "his" : "her")} " +
$"{client.Pet.Schedule[0]} shots.\n" +
"Please call our office at 1-900-382-5633 to make an appointment.\n\n" +
"Thank you,\n" +
"Eastern Veterinary"
);
You do lose compile-time concatenation this way. Each interpolated string gets turned into a call to string.Format
by the compiler, and their results are concatenated at run time. That means this is a sacrifice of run-time performance for readability. Most of the time, it's a worthwhile sacrifice, because the run-time penalty is negligible. In performance critical code, however, you may need to profile different solutions.
1
You can see this in the C# specification:
... the following constructs are permitted in constant expressions:
...
- The predefined + ... binary operator...
You can also verify it with a little code:
const string s =
"This compiles successfully, " +
"and you can see that it will " +
"all be one string (named `s`) " +
"at run time";