176

Why would anyone use String.Format in C# and VB .NET as opposed to the concatenation operators (& in VB, and + in C#)?

What is the main difference? Why are everyone so interested in using String.Format? I am very curious.

one noa
  • 345
  • 1
  • 3
  • 10
Mathias Lykkegaard Lorenzen
  • 15,031
  • 23
  • 100
  • 187

7 Answers7

411

I can see a number of reasons:

Readability

string s = string.Format("Hey, {0} it is the {1}st day of {2}.  I feel {3}!", _name, _day, _month, _feeling);

vs:

string s = "Hey," + _name + " it is the " + _day + "st day of " + _month + ".  I feel " + feeling + "!";

Format Specifiers (and this includes the fact you can write custom formatters)

string s = string.Format("Invoice number: {0:0000}", _invoiceNum);

vs:

string s = "Invoice Number = " + ("0000" + _invoiceNum).Substr(..... /*can't even be bothered to type it*/)

String Template Persistence

What if I want to store string templates in the database? With string formatting:

_id         _translation
  1         Welcome {0} to {1}.  Today is {2}.
  2         You have {0} products in your basket.
  3         Thank-you for your order.  Your {0} will arrive in {1} working days.

vs:

_id         _translation
  1         Welcome
  2         to
  3         .  Today is
  4         . 
  5         You have
  6         products in your basket.
  7         Someone
  8         just shoot
  9         the developer.
Neuron
  • 5,141
  • 5
  • 38
  • 59
Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • 1
    I agree on both but I think that the main reason is that you can read the string without the noise of the variable names inside. – Ignacio Soler Garcia Jan 12 '11 at 17:10
  • 2
    I don't think the separation of concerns provided by removing string templates from your code should be under-estimated. If some bad wording becomes an issue, this can mean the difference between a simple config change or database update, and a full blown emergency change. – SamStephens Jan 12 '11 at 17:19
  • 201
    +1 for the `Someone just shoot the developer.` ;-) – Tim Schmelter Jan 12 '11 at 17:20
  • 13
    For your 'substr' example you should actually use _invoiceNum.ToString("00000"). ToString supports the same composite formatting settings as string.Format() When you have just a single value to be formatted ToString() is often simpler/clearer than Format(). – Ash Jan 17 '11 at 01:40
  • @Ash, absolutely correct. I used the elongated awful format as I sort of assumed that someone who might use concatenation everywhere might also choose the hard way and shun formatting completely :) But, you have a point! – Moo-Juice Jan 17 '11 at 07:57
  • 28
    I don't know about you, but I read the one without formatting better. Especially when I want to know what goes where, I have to go back and forth between the text and the params, and that's not even counting the possibility of miscounting and getting it wrong (that may not be an issue with fewer parameters, but go over 10 and it stops being fun). As Ashley pointed out, the second point is null if you use the formatting built in the ToString method. I agree with the third one, but I don't think I'll ever use it outside of that particular case. – Yandros Oct 17 '11 at 18:38
  • 2
    Your readability example sure looks like a clear win... for the concat approach. Why would I _want_ to have to scan the precise order of arguments to determine which one goes where? – Eamon Nerbonne Jan 29 '13 at 14:29
  • 8
    +1 - Also using `String.Format` is faster and uses less overhead. Using concat `+`/`&` has to rebuild the string each time which can be very bad in large string objects. The very definition of a `string` is that it should be defined once and reused many times.(Many books teach us to use concat as examples but never tell us about performance!!) Building string should use `StringBuilder` which is even faster than `String.Format` ! VERY GOOD ANSWER- Developers need to learn to write readable code and keep performance in mind too! – Piotr Kula Feb 12 '13 at 10:41
  • 10
    @ppumkin That's not true. When you have a specific number of + operators all specified in a single expression it will be converted, by the compiler, into a single call to `string.Concat`, and there will not be any intermediate strings created. Using a StringBuilder would in fact *hurt* performance, not help it, since Concat can create an internal buffer of exactly the right size from the start. A SB is used when you have some sort of loop or other control block such that the number of strings being concatted isn't known by the compiler at compile time. – Servy Mar 19 '13 at 14:37
  • Well - I went back to the MSDN and read a bit- I thouhg it said somehwere that using `&` or `+` rebuilds the String making it less efficient. [Then i found this practical test](http://www.codeproject.com/Articles/14936/StringBuilder-vs-String-Fast-String-Operations-wit) Which yields interesting results. The table near the end- the author advises to use `+` for 2 strings but `String.Join` for more than 2! [OK - Jon Skeet also agrees with that in this answer](http://stackoverflow.com/a/585897/706363) - Can you give us a reference to prove your comment.I know you have good rep and all.. – Piotr Kula Mar 19 '13 at 14:55
  • [And this article just says. IT DOESN'T MATTER](http://www.codinghorror.com/blog/2009/01/the-sad-tragedy-of-micro-optimization-theater.html) :) Heheh, As long as we don't use the immutable strings in massive loops. – Piotr Kula Mar 19 '13 at 15:02
  • How to write this using String.Format() Function... Ex: String.Format(" {0} ","NDD-255252"); How to just display First 3 Chars only using String Formatting... Help me.. – Rahul Uttarkar Mar 18 '14 at 10:11
  • @Drua, post a question? – Moo-Juice Mar 18 '14 at 13:46
  • I can't believe C# doesn't inherently support named string format parameters, e.g. {"foo"}. – wisbucky Oct 03 '14 at 22:11
  • @wisbucky, would be easy enough to implement. However, ordinal indexes are far more performant - we're spending enough time with strings, why spend more? :) – Moo-Juice Oct 05 '14 at 19:15
  • 1
    As an additional argument in favor of concat being more legible, your sample code says `"the {1}st day"`, which reads well because it looks like first, but in reality it also says seconst, thirst, fourst, fifst, etc. The error is much easier to see at a glance when the code reads `"the " + _day + "st"`. – octothorpentine Aug 13 '15 at 18:24
  • 2
    I would also like to mention here that C# now supports string interpolation, which comes with the benefits of string.format, yet offers a shorter syntax and is easier to read, due to the inline evaluation of variables and functions. http://www.dotnetperls.com/string-interpolation. I recommend you use that over string.format. – CShark May 26 '16 at 17:35
  • @DaffyPunk Great option to point out. That's really neat. It'll basically interpret as code whatever you through at it (within reason). Also, the performance testing in your link shows that `string.Format` is slower than `string.Concat`, which stands in agreement with Servy's reply to ppumpkin. – u8it Jul 27 '16 at 22:24
92

Besides being a bit easier to read and adding a few more operators, it's also beneficial if your application is internationalized. A lot of times the variables are numbers or key words which will be in a different order for different languages. By using String.Format, your code can remain unchanged while different strings will go into resource files. So, the code would end up being

String.Format(resource.GetString("MyResourceString"), str1, str2, str3);

While your resource strings end up being

English: "blah blah {0} blah blah {1} blah {2}"

Russian: "{0} blet blet blet {2} blet {1}"

Where Russian may have different rules on how things get addressed so the order is different or sentence structure is different.

Neuron
  • 5,141
  • 5
  • 38
  • 59
doobop
  • 4,465
  • 2
  • 28
  • 39
27

First, I find

string s = String.Format(
    "Your order {0} will be delivered on {1:yyyy-MM-dd}. Your total cost is {2:C}.",
    orderNumber,
    orderDeliveryDate,
    orderCost
);

far easier to read, write and maintain than

string s = "Your order " +
           orderNumber.ToString() +
           " will be delivered on " +
           orderDeliveryDate.ToString("yyyy-MM-dd") +
           "." +
           "Your total cost is " +
           orderCost.ToString("C") + 
           ".";

Look how much more maintainable the following is

string s = String.Format(
    "Year = {0:yyyy}, Month = {0:MM}, Day = {0:dd}",
    date
);

over the alternative where you'd have to repeat date three times.

Second, the format specifiers that String.Format provides give you great flexibility over the output of the string in a way that is easier to read, write and maintain than just using plain old concatenation. Additionally, it's easier to get culture concerns right with String.Format.

Third, when performance does matter, String.Format will outperform concatenation. Behind the scenes it uses a StringBuilder and avoids the Schlemiel the Painter problem.

jason
  • 236,483
  • 35
  • 423
  • 525
  • 1
    Just a note: There is no Schlemiel the Painter problem with repeated `+`s in a line. They are compiled to a single `string.Concat` call. – porges Mar 01 '11 at 21:46
  • Actually `string.Concat` outperforms `String.Format` (at least for a single short strings). However there are many many factor involved (which can make one more efficient than the other). In situations in which the execution time would matter much (repeating same operation countless times), the speed saved by using `string.Concat` will be negligible though. – jahu Oct 16 '14 at 12:01
  • You don't have to call ToString() explicitly. `"Your order " + orderNumber.ToString()` is same as `"Your order " + orderNumber` – Arthur Stankevich Dec 25 '14 at 06:10
  • 1
    There actually **is** a Schlemiel the Painter problem with `+`s, it's just a bit delayed. `String.Concat` only takes up to four arguments, so the way five or more strings are joined via `+`s is by concatting them in groups of up to four, and then concatting **those** strings, and so on. – octothorpentine Aug 13 '15 at 18:46
17

Several reasons:

  1. String.Format() is very powerful. You can use simple format indicators (like fixed width, currency, character lengths, etc) right in the format string. You can even create your own format providers for things like expanding enums, mapping specific inputs to much more complicated outputs, or localization.
  2. You can do some powerful things by putting format strings in configuration files.
  3. String.Format() is often faster, as it uses a StringBuilder and an efficient state machine behind the scenes, whereas string concatenation in .Net is relatively slow. For small strings the difference is negligible, but it can be noticable as the size of the string and number of substituted values increases.
  4. String.Format() is actually more familiar to many programmers, especially those coming from backgrounds that use variants of the old C printf() function.

Finally, don't forget StringBuilder.AppendFormat(). String.Format() actually uses this method behind the scenes*, and going to the StringBuilder directly can give you a kind of hybrid approach: explicitly use .Append() (analogous to concatenation) for some parts of a large string, and use .AppendFormat() in others.


* [edit] Original answer is now 8 years old, and I've since seen an indication this may have changed when string interpolation was added to .Net. However, I haven't gone back to the reference source to verify the change yet.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • 3
    `string.Format` usually won't be faster than a few string concatenations, because the format string also needs to be parsed and copied. – Dirk Vollmar Jan 12 '11 at 17:16
  • Thanks for the update. In fact, there is another caveat with `string.Format` as compared to concatenation + `ToString()`: value types are boxed as described here: http://jeffbarnes.net/blog/post/2006/08/08/Avoid-Boxing-When-Using-StringFormat-with-Value-Types.aspx. Nonetheless, `string.Format` is a very powerful and great tool and performance usually not the most important criteria. – Dirk Vollmar Jan 12 '11 at 17:26
  • 6
    In reference to #3: String builder is not faster than concatenation. The myth that it is is supported by "tests" that actually do concatenation on different lines (or in a loop). When all concatenation is done on a single line, the compiler translates it into a string.append(paramaarray) call, which is the most efficient out of all options. During a string.append call, the exact size of the destination string is known ahead of time and can be allocated immediately and each character copied only once. – csauve Jan 12 '11 at 17:44
5

String.Format adds many options in addition to the concatenation operators, including the ability to specify the specific format of each item added into the string.

For details on what is possible, I'd recommend reading the section on MSDN titled Composite Formatting. It explains the advantage of String.Format (as well as xxx.WriteLine and other methods that support composite formatting) over normal concatenation operators.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
4

There's interesting stuff on the performance aspects in this question

However I personally would still recommend string.Format unless performance is critical for readability reasons.

string.Format("{0}: {1}", key, value);

Is more readable than

key + ": " + value

For instance. Also provides a nice separation of concerns. Means you can have

string.Format(GetConfigValue("KeyValueFormat"), key, value);

And then changing your key value format from "{0}: {1}" to "{0} - {1}" becomes a config change rather than a code change.

string.Format also has a bunch of format provision built into it, integers, date formatting, etc.

Neuron
  • 5,141
  • 5
  • 38
  • 59
SamStephens
  • 5,721
  • 6
  • 36
  • 44
  • If you're interested in the performance aspect, you might find this other question interesting: http://stackoverflow.com/questions/761121/performance-issue-comparing-to-string-format – Joel Coehoorn Jan 12 '11 at 17:18
2

One reason it is not preferable to write the string like 'string +"Value"+ string' is because of Localization. In cases where localization is occurring we want the localized string to be correctly formatted, which could be very different from the language being coded in.

For example we need to show the following error in different languages:

MessageBox.Show(String.Format(ErrorManager.GetError("PIDV001").Description, proposalvalue.ProposalSource)

where

'ErrorCollector.GetError("ERR001").ErrorDescription' returns a string like "Your ID {0} is not valid". This message must be localized in many languages. In that case we can't use + in C#. We need to follow string.format.

jth41
  • 3,808
  • 9
  • 59
  • 109