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

发布于 2024-08-06 14:22:42 字数 298 浏览 4 评论 0原文

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

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

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夜还是长夜 2024-08-13 14:22:42

根据这里的答案和讨论,我做了一些更多的调查。这是我发现的:

  • 当您使用不带任何参数的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()

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.

跨年 2024-08-13 14:22:42

这两种方法并不等同:第一种方法是使用 CurrentCulture。这可能会导致在某些文化中出现额外的点/逗号(我没有例子)。

当您使用InvariantCulture时,您可以确定始终使用相同的格式。

编辑:并且,如果您使用CodeAnalysis,那么当您不使用CultureInfo时,它会抱怨。

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.

故人如初 2024-08-13 14:22:42

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

下面的代码在我的电脑上给出了“测试了 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.");

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(
quot;{culture.DisplayName}: {s1} != {s2}");
            diffsFound++;
        }
    }
}

Console.WriteLine(
quot;{cultures.Length} cultures tested, {diffsFound} differences found.");
伪心 2024-08-13 14:22:42

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

(~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

从此见与不见 2024-08-13 14:22:42

正如我所见,第一个将使用计算机的默认区域性格式化一个至少包含一个字符的数字。
第二个将根据 InvariantCulture 规则将其格式化为数字。

鲍比

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

云淡月浅 2024-08-13 14:22:42

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);

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);
绝影如岚 2024-08-13 14:22:42

如果您想确保指定“无论如何都没有格式”,我个人认为您拥有的第一个选项:

123456789.ToString("0");

更好地传达意图。缺点是如果区域性覆盖了您正在使用的数字类型的格式字符串“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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文