17

无论当前环境如何,我都想确保我的应用程序中的某些数字在打印时没有任何分隔符、分组等。似乎以下两种方法产生相同的结果(可能更多):

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

您是否知道任何边缘情况或怪癖?哪个更“正确”?你会用哪一个?

我曾经使用第二个,但最近我找到了第一个并开始使用它,因为它不需要额外的using System.Globalization.

4

7 回答 7

26

根据此处的答案和讨论,我进行了更多调查。这是我发现的:

  • 当您12345678.ToString()不带任何参数使用时,.NET 使用一般格式说明符“G”,它仅受 NumberFormatInfo.NegativeSign、NumberFormatInfo 影响。NumberDecimalSeparator、NumberFormatInfo.NumberDecimalDigits 和 NumberFormatInfo.PositiveSign。对我来说,这表明在任何文化中12345678.ToString()都应该始终产生“12345678”。

  • 如果要分隔数字,则需要使用数字格式说明符“N”(或者,当然,提供自定义格式字符串)。数字分组也适用于“C”和“P”。

  • 不变的文化确实指定了数字分组(当然是 3 位数字)和数字分隔符。所以123456789.ToString(CultureInfo.InvariantCulture)产生“123456789”的原因不是因为文化不变,而是因为默认的通用数字格式说明符“G”。

所以我会说结论是完全可以不用担心任何额外的参数而只需使用

12345678.ToString()

我认为这是所有情况中最好的,因为这意味着通常您甚至不需要调用ToString(),因为大多数打印/写入函数都接受各种参数并ToString()为您执行。

于 2009-09-29T09:44:42.483 回答
9

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.

于 2009-09-28T15:07:49.103 回答
4

.ToString().ToString(CultureInfo.InvariantCulture)似乎对整数给出了相同的结果。

下面的代码在我的 PC 上给出了“测试了 809 种文化,发现了 0 种差异”的结果(对于 .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.");
于 2016-05-25T06:29:19.350 回答
3

(约 5 年后...)

我正在查找这个确切的问题,但由于没有公认的答案,即使 Jan Zich 是正确的,我想我会整理一个小例子来测试这个。

我还要说 .ToString()、.ToString("0") 和 .ToString(Any Culture Info) 之间没有区别(就整数和小数而言)

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 片段

于 2015-02-09T16:36:16.043 回答
2

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

于 2009-09-28T15:07:20.557 回答
1

2行做不同的事情。第一行使用本地文化对数字进行格式化,第二行将其转换为字符串而不进行格式化,但使用 CultureInfo.InvariantCulture。

您将 CultureInfo.InvariantCulture 与此类方法(ToString、ToLower ...)一起使用,以确保当任何软件(数据库、另一个库 ...)使用该值时,无论其文化是什么,都会导致相同的值,当他们可以获取该值时,他们可以继续处理它。但是,如果您不使用它,则其他软件必须弄清楚您的文化是什么。你的意思是用逗号或其他东西的小数分隔符......?

当您想在库、数据库之间交换/使用值并使用 CultureInfo.CurrentCulture 向应用程序的用户展示时,所有和所有都使用 CultureInfo.InvariantCulture。

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

// for your application users
string mystring2 = 1234.ToString("0", CultureInfo.CurrentCulture);
于 2010-11-14T08:09:21.407 回答
0

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.

于 2009-09-28T15:06:08.547 回答