views:

1127

answers:

4

I would like to make sure that certain numbers in my application are printed without any separators, groupings etc. no matter what the current environment is. It seems that the following two methods produce the same results (there are possibly more):

123456789.ToString("0");
123456789.ToString(CultureInfo.InvariantCulture);

Are you aware of any edge cases or quirks? Which one is more "correct"? Which one would you use?

I used to use the second one, but recently I found the first one and started using it because it does not require the additional using System.Globalization.

+1  A: 

If you're wanting to make sure to specify "no formatting, no matter what" I personally think the first option you have:

123456789.ToString("0");

better communicates the intent. The downside would be if a culture overrode the format string of "0" for the numeric type you are using.

Nicolas Webb
Oh, I did now know that you can override the format strings? I need to look it up.
Jan Zich
Are you sure about the overloading? MSDN (http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx) says: "Any other single character [than one of those standard] throws a FormatException at run time."
Jan Zich
I was not sure if this was the case or not. I see a quick trip to the MSDN library would have shown me :).
Nicolas Webb
+1  A: 

As I see it, The first one will format is a number with at least one character using the default culture of the computer. The second will format it as a number depending on the InvariantCulture rules.

Bobby

Bobby
Correct me if I’m wrong: I thought that no digit grouping, separator etc. apply to 123456789.ToString("0")?
Jan Zich
Uhhh...it really doesn't. I've mistaken it for a formatting symbol like "N0", which does apply the current culture rules. You're right, since the 0 is a direct formatting it doesn't apply _any_ culture information.Though, someone could also use 123456789.ToString(); .
Bobby
+3  A: 

The two methods are not equivalent: the first is using the CurrentCulture. This could lead to extra dots/commas in certain cultures (I don't have examples).

When you use InvariantCulture you are certain that always the same formatting is used.

Edit: And, if you use CodeAnalysis, that will complain when you don't use a CultureInfo.

Hans Kesting
I tested the first one by modifying the current thread culture, and it did not affect it. I think the "0" means: at least one digit + no digit grouping or separators. If I wanted to have some digit grouping or separators, I think I would have to do something like "000,000".
Jan Zich
But you are right: InvariantCulture "sounds" more explicit. Even MSDN says "... it is associated with the English language but not with any country/region". Hmm, when I think about more, ToString(CultureInfo.InvariantCulture), it means that the number if formatted using the "G". It all just happens to work ONLY because "G" does not seem to be using any grouping. BUT (I just looked it up) the invariant culture has some grouping specified. For instance, try 12345789.ToString("N", CultureInfo.InvariantCulture).
Jan Zich
+1  A: 

Based on the answers and the discussion here, I did some more investigation. Here is what I found:

  • When you use 12345678.ToString() without any arguments, .NET uses general the general format specifier "G" which if affected only by NumberFormatInfo.NegativeSign, NumberFormatInfo. NumberDecimalSeparator, NumberFormatInfo.NumberDecimalDigits and NumberFormatInfo.PositiveSign. To me this says that in any culture 12345678.ToString() should always produce "12345678".

  • If you want to separate digits, you need to use the numeric format specifier "N" (or, of course, to provide a custom format string). The digit grouping also applies to "C" and "P".

  • The invariant culture does indeed specify digit grouping (by 3 digits, of course) and a digit separator. So the reason that 123456789.ToString(CultureInfo.InvariantCulture) produces "123456789" is not because of the invariant culture, but it’s because of the default general numeric format specifier "G".

So I would say that the conclusion is that it’s perfectly OK not to worry about any extra arguments and just use:

12345678.ToString()

I think that this the best from all cases because it means that usually you don’t need to even call ToString() because most of the print/write functions accept all sorts of arguments and do the ToString() for you.

Jan Zich