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);
Related
Currently I am mostly doing the localization by putting key-value pairs into a Resources.resw file. So I wonder about how I should localize strings that need formatting or say strings with different grammar orders in different languages. It might be easier to understand what I mean with the examples below.
For example, just as this part in the official document for localization suggests, one language can have the date format of
string.Format("Every {0} {1}", monthName, dayNumber);
while the other uses
string.Format("Every {1} {0}", monthName, dayNumber);
In this situation, what is the best way to localize such a string?
Things/Grammars can be way more complicated than this example. The suggestion in the official document doesn't look good to me because a date can be unpredictable. Or may be you can enumerate the date, but that requires a lot of work. Or let's say we have a string that takes user input, like
string.Format("Do you want to delete {name}?", name);
In another language it might have this grammar order
string.Format("You want to delete {name} do?", name);
It is impossible to localize the whole sentence as the example suggests in the document.
The only way of avoiding situation that I can think of is not to put user input....
If you have access to the date you could use The Month ("M", "m") Format Specifier
From the documentation:
DateTime date1 = new DateTime(2008, 4, 10, 6, 30, 0);
Console.WriteLine(date1.ToString("m",
CultureInfo.CreateSpecificCulture("en-us")));
// Displays April 10
Console.WriteLine(date1.ToString("m",
CultureInfo.CreateSpecificCulture("ms-MY")));
// Displays 10 April
For string.Format("Do you want to delete {name}?", name); you can
$"Do you want to delete the following user? '{name}'";
One way I just found out is to put this key-value pair into the Resources.resw:
Key: RemoveText
Value: Do you want to delete {0}?
After you get the localized string like doing
var msg = Localize('RemoveText');
Then
var result = string.Format(msg, name)
can give you the expected result.
Basically, you need to put {0} appropriately in every language. The only flaw of this solution is that {0} should not be allowed in the user input.
If you still want {0} to appear, you can change {0} to other strings that you think are too complicated and long for user to type in, for example '{usersAreVeryUnlikelyToTypeInThisInTheirInputs}'. And then use
msg.replace('{usersAreVeryUnlikelyToTypeInThisInTheirInputs}', name)
to get the localized string.
I'm writing a little text-based adventure in the console as one of my first projects in C#.
At a certain point, I want to do the following:
Console.WriteLine(intro);
var name = Console.ReadLine();
Console.Clear();
Console.WriteLine(replyOne, name, replyTwo);
However, on that last line, only the first variable (replyOne) is displayed. How can I display all the values?
Depends on what's on replyOne, but you are using a Console.WriteLine overload that takes a format string as the first argument and a number of objects for substitution of that format string (this one). That's what's called Composite Formatting in .NET
If what you want to do is concatenate the strings, you can do it in several ways:
Pass only one string to Console.WriteLine:
Console.WriteLine(replyOne + name + replyTwo);
Use a format string... this would use the same overload you are using now, but passing a formatting string for substitution on the first argument:
Console.WriteLine("{0}{1}{2}", replyOne, name, replyTwo);
Use an interpolated string (C# 6 and up only)
Console.WriteLine($"{replyOne}{name}{replyTwo}");
In the multi-argument overloads of the Console.WriteLine the first parameter is supposed to be a format string, and everything else as a substitution values.
See Console.WriteLine Method (String, Object) for details.
If you want Console.WriteLine to output a formatted string the first argument has to be the string that contains the placeholders that define the formatting. So assuming you just want to output the three strings consecutively, you'll need something like this:
Console.WriteLine("{0} {1} {2}", replyOne, name, replyTwo);
which will output the three strings separated by spaces.
You can replace the spaces by commas, newlines (\n) or tabs (\t) to get the formatting you need.
Try this instead:
Console.WriteLine(replyOne + name + replyTwo);
Or something similar.
As you're calling the method right now, it's treating the replyOne value as the format for the output, not an individual output item. And of course, your format doesn't have a {0} or {1} for the format arguments in the call, name and replyTwo, so they are omitted.
You can just concatenate the output text yourself, as above, as use that as the entire format (without any format arguments at all).
There are, of course, lots of other options for formatting the output. The above fits what you've posted so far.
Console.WriteLine("{0},{1},{2}",replyOne,name,replyTwo);
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.
What would be the best way to accomplish something like this?
Suppose I have the following pair of Resource strings.
BadRequestParameter: Potential bad request aborted before execution.
RequiredParameterConstraint: {0} parameter requires a value. {1}
And suppose I want to set {1} on the second one, to the value of BadRequestParameter. I could easily do that using string.Format. But now suppose I have lots of Resource strings like the second one, all of which include some other Resource string in them.
What would be the best way to code this? Is using string.Format repeateadly in each case really all that I can do?
Update
I'll try to explain myself better. These are the resource strings I actually have:
BadRequestParameter Potential bad request aborted before execution.
EmptyVector Vectorized requests require at least one element. {0}
OverflownVector Vectorized requests can take at most one hundred elements. {0}
RequiredParamConstraint {0} parameter requires a value. {1}
SortMinMaxConstraint {0} parameter value '{1}' does not allow Min or Max parameters in this query. {2}
SortRangeTypeConstraint Expected {0} parameter Type '{1}'. Actual: '{2}'. {3}
SortValueConstraint {0} parameter does not allow '{1}' as a value in this query. {2}
I'd like to avoid writing the string in BadRequestParameter at the end of each of those lines. Therefore, I added a format at the end of those strings. The issue now is that I'd like to somehow auto-reference {x} to BadRequestParameter, in order to avoid having to make calls like
string.Format(Error.EmptyVector, Error.BadRequestParameter);
I have lots of Resource strings like the second one, all of which include some other Resource string in them.
Instead of storing pre-made format strings ready for use, you could store raw material for building real format strings, and add code to expand them pro grammatically before use. For example, you could store strings like this:
BadRequestParameter: Potential bad request aborted before execution.
SupportNumber: (123)456-7890
CallTechSupport: You need to call technical support at {SupportNumber}.
RequiredParameterConstraint: {{0}} parameter requires a value. {BadRequestParameter} {CallTechSupport}
Of course passing these strings to string.Format as-is is not going to work. You need to parse these strings, for example with RegExps, and find all instances where you have a word between curly braces, instead of a number. You could then replace each word with its sequence number, and produce an array of parameters based on the names that you find between curly braces. In this case, you will get these two values (pseudocode):
formatString = "{{0}} parameter requires a value. {0} {1}";
// You replaced {BadRequestParameter} with {0} and {CallTechSupport} with {1}
parameters = {
"Potential bad request aborted before execution."
, "You need to call technical support at (123)456-7890."
};
Note: Of course, producing this array of parameters required recursion.
At this point, you can invoke string.Format to produce your final string:
var res = string.Format(formatString, parameters);
This returns the string that has resource strings pre-replaced for your callers:
"{0} parameter requires a value. Potential bad request aborted before execution. You need to call technical support at (123)456-7890."
The callers can now use this string for formatting, without bothering with other resource values.
Yes :-) unless you want to make a helper method that is shorter, but that would really just be for convenience sake
public static string f(string format, params object[] p)
{
return string.Format(format, p);
}
IF you treat the argument indicators {#} as wild cards then why would it make sense for you to pre-fill them inside of your resource.
I see absolutely nothing wrong with
String.Format(RequiredParamterConstraint, "something", BadRequestParameter);
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.