简体   繁体   中英

ToString(“0”) versus ToString(CultureInfo.InvariantCulture)

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 .

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 is 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.

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 .

(~5 years later...)

I was looking up this exact question, but since there was no accepted answer and even though Jan Zich is correct I thought I would put together a little example to test this.

I would also go so far to say that there is no difference between .ToString(), .ToString("0"), and .ToString(Any Culture Info) (as far as integers and decimals are concerned)

var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures)
    .Except(CultureInfo.GetCultures(CultureTypes.SpecificCultures));

foreach(var c in cultures){
    var num = (int.MinValue);/*
    var num = (int.MaxValue);/*
    var num = (decimal.MinValue);/*
    var num = (decimal.MaxValue);/*
--*/

    var s1 = num.ToString("0") ;
    var s2 = num.ToString(c);
    if(s1 != s2){
        var s = string.Format("{2}:  {0}    {1}",s1,s2,c);
        s.Dump();
    }
}

LinqPad snippet

The .ToString() and .ToString(CultureInfo.InvariantCulture) seems give the same result for integers.

The code below gives " 809 cultures tested, 0 differences found " result on my PC (for .NET Framework 4.7.2):

var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures).ToArray();
var numbers = new[] { 0, -1, 1, int.MinValue, int.MaxValue };

var diffsFound = 0;
foreach (var culture in cultures)
{
    foreach (var number in numbers)
    {
        var s1 = number.ToString();
        var s2 = number.ToString(culture);
        if (s1 != s2)
        {
            Console.WriteLine($"{culture.DisplayName}: {s1} != {s2}");
            diffsFound++;
        }
    }
}

Console.WriteLine($"{cultures.Length} cultures tested, {diffsFound} differences found.");

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

2 lines do different things. The first line formats the number with the local culture and the second one converts it to string without formatting but using CultureInfo.InvariantCulture.

You use CultureInfo.InvariantCulture with this kind of methods (ToString, ToLower ...) to make sure that when the value is used by any software (database, another library ...), no matter what their culture is, it will result the same value and when they can pick up this value, they can continue processing it. However if you don't use this the other software has to figure out what your culture is. Did you mean decimal separator with comma or something else ... ?

All and all use CultureInfo.InvariantCulture when you want to exchange/use values among libraries, databases and use CultureInfo.CurrentCulture to show to the users of your application.

// for softwares
string mystring1 = 1234.ToString("0", CultureInfo.InvariantCulture);

// for your application users
string mystring2 = 1234.ToString("0", CultureInfo.CurrentCulture);

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM