Why use String.Format? [duplicate] - c#

This question already has answers here:
String output: format or concat in C#?
(32 answers)
Closed 9 years ago.
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.

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.

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.

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.

Several reasons:
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.
You can do some powerful things by putting format strings in configuration files.
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.
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.

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.

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.

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.

Related

Declaring long strings that use string interpolation in C# 6

I usually wrap long strings by concatenating them:
Log.Debug("I am a long string. So long that I must " +
"be on multiple lines to be feasible.");
This is perfectly efficient, since the compiler handles concatenation of string literals. I also consider it the cleanest way to handle this problem (the options are weighed here).
This approach worked well with String.Format:
Log.Debug(String.Format("Must resize {0} x {1} image " +
"to {2} x {3} for reasons.", image.Width, image.Height,
resizedImage.Width, resizedImage.Height));
However, I now wish to never use String.Format again in these situations, since C# 6's string interpolation is much more readable. My concern is that I no longer have an efficient, yet clean way to format long strings.
My question is if the compiler can somehow optimize something like
Log.Debug($"Must resize {image.Width} x {image.Height} image " +
$"to {resizedImage.Width} x {resizedImage.Height} for reasons.");
into the above String.Format equivalent or if there's an alternative approach that I can use that won't be less efficient (due to the unnecessary concatenation) while also keeping my code cleanly structured (as per the points raised in the link above).
This program:
var name = "Bobby Tables";
var age = 8;
String msg = $"I'm {name} and" +
$" I'm {age} years old";
is compiled as if you had written:
var name = "Bobby Tables";
var age = 8;
String msg = String.Concat(String.Format("I'm {0} and", name),
String.Format(" I'm {0} years old", age));
You see the difficulty in getting rid of the Concat - the compiler has re-written our interpolation literals to use the indexed formatters that String.Format expects, but each string has to number its parameters from 0. Naively concatenating them would cause them both to insert name. To get this to work out correctly, there would have to be state maintained between invocations of the $ parser so that the second string is reformatted as " I'm {1} years old". Alternatively, the compiler could try to apply the same kind of analysis it does for concatenation of string literals. I think this would be a legal optimization even though string interpolation can have side effects, but I wouldn't be surprised if it turned out there was a corner case under which interpolated string concatenation changed program behavior. Neither sounds impossible, especially given the logic is already there to detect a similar condition for string literals, but I can see why this feature didn't make it into the first release.
I would write the code in the way that you feel is cleanest and most readable, and not worry about micro-inefficiencies unless they prove to be a problem. The old saying about code being primarily for humans to understand holds here.
Maybe it would be not as readable as with + but by all means, it is possible. You just have to break line between { and }:
Log.Debug($#"Must resize {image.Width} x {image.Height} image to {
resizedImage.Width} x {resizedImage.Height} for reasons.");
SO's colouring script does not handle this syntax too well but C# compiler does ;-)
In the specialized case of using this string in HTML (or parsing with whatever parser where multiple whitespaces does not matter), I could recommend you to use #$"" strings (verbatim interpolated string) eg.:
$#"some veeeeeeeeeeery long string {foo}
whatever {bar}"
In c# 6.0:
var planetName = "Bob";
var myName = "Ford";
var formattedStr = $"Hello planet {planetName}, my name is {myName}!";
// formattedStr should be "Hello planet Bob, my name is Ford!"
Then concatenate with stringbuilder:
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(formattedStr);
// Then add the strings you need
Append more strings to stringbuilder.....

What is the difference between these two C# console.write syntaxes?

I'm relatively new to C#. In going through some online practice exercises for C# console apps, I came across something I found to be interesting. If I were asked to output a variable to the screen, I would simply use:
Console.Write(variable);
but when I look this up in various tutorials they say it should be written like this:
Console.Write("{0}", variable);
why is this different way listed as opposed to the way I would naturally do it?
Since you only have one variable, there's no difference. The second version is for writing formatted strings. It works the same way as String.Format Eg:
Console.Write("The {0} Saturday this month is {1:dd MM yyyy}", "First", new DateTime(2015,6,13));
A composite format string contains some combination of actual text and format items that will be substituted with values of corresponding placeholders at run-time.
For example:
string name = "Ahmer";
int age = 22;
Console.WriteLine(string.Format("{0} is {1} yrs old. {0} is old.", name, age))
Output:
Ahmer is 22 yrs old.
A format item is indicated by a 0-based index within a pair of braces. Notice that you can have multiple format items that refer to the same placeholder.
You can also include the format items in any order. At run-time, each format item is evaluated and the appropriate value is substituted. For example:
Console.WriteLine(string.Format("Age: {1}, Name: {0}. {1} {1} {1}..", name, age));
Age:22,Name: Ahmer. 22 22 22
console.write("{0}", variable); is an overload of the Console.WriteLine method which displays a formatted result string to the console. Nevertheless for your case the outputs will be exactly the same.
References:
Console.WriteLine Method (String, Object)
Console.WriteLine Method (String).
As said the output would be the same but String.Format (which quals the overload of Console.Write with two parameters) makes code much easier to read/write/maintain.
But if you are interested in the performance take a look here...
String output: format or concat in C#?
edit: removed old values because testing was not reliable... updated with better results
these lines have been executed 1000000 times, without any console output. From the performance kind of view formatting takes some time when using random values (not that you will normally realise it)
513 ms - string.Format("{0} {1}", p.FirstName, p.LastName);
393 ms - (p.FirstName + " " + p.LastName);

String - " " + vs " " {} [duplicate]

This question already has answers here:
String output: format or concat in C#?
(32 answers)
Closed 8 years ago.
Is there any difference between writing the following two? The code is for C#
String S1 = "The " + Item.Name + " is made of " + Item.Property + " and is at " + Item.Durability + "% durability."
against
String S2 = "The {0} is made of {1} and is at {2} % durability.", Item.Name, Item.Property, Item.Durability
? Assuming that item is populated with, for instance, name of Axe, property of Steel, and durability of 50 as a string.
The second one is faster, assuming you correctly use it with String.Format.
In the first approach, you're internally forcing the system to sequentially build an incrementally larger string, triggering at least a full allocation and internal copy for each of the + operations.
In the second, you're letting internally optimized functions first assess all of the parameters, and allocate a single string to contain the entire end result in one go, and copy it in.
Yes, the second one give to you a single string, for your code is worng, you have to use string.Format method, so it is has a better performance than first one.
String S2 = string.Format("The {0} is made of {1} and is at {2} % durability.", Item.Name, Item.Property, Item.Durability);
The first one will generate a lot of strings and do the concatenation operation between + operator.
If you have a concatenation inside a loop, the recomentation is to use StringBuilder class.
Take a look at this post: Most efficient way to concatenate strings?
Assuming you correct your second example to use String.Format, they should produce the exact same result, yes.
I personally prefer using String.Format because it gives me more control. Also, I've always assumed it might be more efficient, although I've done no testing to verify that.

How to include Variables in Localized Strings?

I'm trying to display a message to the user along the lines of:
"User 5 could not be added"
But how can I add variables to a string that is being placed in a .resx file? I've trying searching for things like "Variables in Localization" "Globalization with Variables" etc, but came up dry.
If I weren't localizing I would write:
Console.Write("User " + userNum + " could not be added");
How can this be accomplished with resources?
You can't do this directly.
What you can do is place a token - a specific string that can be replaced with string.Replace with the value of the variable.
A good candidate for this would be the built in string formatting:
Console.Write(string.Format("User {0} could not be added", userNum));
Assuming userNum has the value 5, the result would be:
User 5 could not be added
You can localize this string with the composite format specifiers.
In teams where I've done internationalization, we generally also created a resource for the format string, something like USER_COULD_NOT_BE_ADDED_FORMAT, and called String.Format (or your environment's equivalent) by passing that resource's value as the format pattern.
Then you'll do Console.Write(String.Format(resourceManager.GetString("USER_COULD_NOT_BE_ADDED_FORMAT"), userNum));
Most localizers either have training in the format strings used by the system they are localizing, or they are provided with guidance in the localization kit that you provide them. So this is not, for example, as high a barrier as making them modify code directly.
You generally need to add a loc comment to the resource ID to explain the positional parameters.
Use Composite Formatting like so:
Console.Write("User {0} could not be added", userNum);
This way you would localize "User {0} could not be added".
you can do that its simple
new lets see how
String.Format(Resource_en.PhoneNumberForEmployeeAlreadyExist,letterForm.EmployeeName[i])
this will gave me dynamic message every time
by the way I'm useing ResXManager
I would use string.Format
http://msdn.microsoft.com/en-us/library/system.string.format.aspx
Console.Write(string.Format("User {0} could not be added", userNum));

When should I use String.Format or String.Concat instead of the concatenation operator?

In C# it is possible to concatenate strings in several different ways:
Using the concatenation operator:
var newString = "The answer is '" + value + "'.";
Using String.Format:
var newString = String.Format("The answer is '{0}'.", value);
Using String.Concat:
var newString = String.Concat("The answer is '", value, "'.");
What are the advantages / disadvantages of each of these methods? When should I prefer one over the others?
The question arises because of a debate between developers. One never uses String.Format for concatenation - he argues that this is for formatting strings, not for concatenation, and that is is always unreadable because the items in the string are expressed in the wrong order. The other frequently uses String.Format for concatenation, because he thinks it makes the code easier to read, especially where there are several sets of quotes involved. Both these developers also use the concatenation operator and String.Builder, too.
Concerning speed it almost always doesn't matter.
var answer = "Use what makes " + "the code most easy " + "to read";
I usually use string.Format when I've chaining together more than 2 or 3 values, as it makes it easier to see what the final result would look like. Concatenating the strings is slow, as you need to create a new string object for each operation.
If you need to join more than 5 strings, use StringBuilder as it would be much faster.
Performance considerations are often the driver behind this decision. See this article by Ayende.
I normally go for readability, and would tend towards using Format. Most code is written once and read multiple times, so making sure the reader can quickly understand what's beening stated is more important (to me).
It is curious, but String.Format internally use StringBuilder.AppendFormat(). For example, String.Format code is looking like:
public static string Format(IFormatProvider provider, string format, params object[] args)
{
if (format == null || args == null)
throw new ArgumentNullException((format == null ? "format" : "args"));
StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
builder.AppendFormat(provider, format, args);
return builder.ToString();
}
More about this you can find here. So, why we haven't mentioned here about StringBuilder.AppendFormat()!
Regarding to main point of question:
The key is to pick the best tool for the job. What do I mean? Consider these awesome words of wisdom:
* Concatenate (+) is best at concatenating.
* StringBuilder is best when you need to building.
* Format is best at formatting.
It's not recommend to store string in code so if you will decide to extract your strings from code then with String.Format it would be easier to do
This is an article on memory usage for various concatenation methods and compiler optimizations used to generate the IL. Concatenation methods and optimization issue

Categories