Int32.ToString()是特定于文化的吗?


67

我正在运行ReSharper的Beta版,它为以下代码提供警告:

int id;
// ...
DoSomethingWith(id.ToString());

该警告正在发生id.ToString(),它告诉我“在字符串转换中明确指定区域性”。我理解警告,并且知道如何解决-只是将代码更改为更加笨拙id.ToString(CultureInfo.InvariantCulture)

但是我的问题是:那有必要吗?我的意思是,当您使用类似DateTime(不同的区域性具有不同的日期格式)和Double(不同的字符用于小数点)类型时,指定区域性很重要。但是Int32.ToString(),至少在美国和不变文化中,根本没有添加任何格式。没有逗号,没有小数点,没有美元符号,什么都没有。那么根据文化的不同会有什么变化?

当您调用无参数时,是否存在某些文化实际上会添加某种格式Int32.ToString()?还是这是ReSharper Beta中的错误,并且此警告确实不适用Int32(在这种情况下,我将提交ReSharper错误报告)?


您正在使用哪个ReSharper版本?据我所知,目前Beta中没有任何ReSharper版本...
Kiley Naro

@KileyNaro:ReSharper 6.1自11月初以来一直在EAP中使用。
乔·怀特

还要注意,Visual Studio代码分析(aka FxCop)会对此表示抱怨,并让您明确设置区域性。因此,这实际上不是Resharper的错。
Polyfun 2011年

@ShellShock,当然;ReSharper只是启发了这个问题,但是这个问题本身是有效的,特别是因为答案令人惊讶。
乔·怀特

2
6.1在调用ToString()的代码中发现了很多问题,但对string.Format()似乎不起作用吗?
斯蒂芬·肯尼迪

Answers:


64

操作系统允许更改数字的号。

Control panel -> 
   Language and regional settings -> 
         Additional settings -> 
             Negative sign

因此,当前的文化可能已经超越了负面迹象。在这种情况下,您需要遵守区域设置,这是发出警告的原因。您还可以通过编程方式更改负号:

    CultureInfo culture = Thread.CurrentThread.CurrentCulture;
    // Make a writable clone
    culture = (CultureInfo) culture.Clone();
    culture.NumberFormat.NegativeSign = "!";

3
您是否有能做到这一点的文化榜样?
parapura rajkumar 2011年

您可以在OS设置中进行更改。
DanielPeñalba'11

20
我不确定是否有任何文化使用不同的负号,但是不久前一位客户报告了一个错误,因为我们的产品无法解析负值,令我惊讶的是,这个疯子被负号改写为“!”。 。为什么?不知道。
丹尼尔·佩纳尔巴(DanielPeñalba)

3
我很高兴没有人尝试与他交换CSV文件。您能想象所有数字数据都重新解释为字符串时的痛苦吗?
Donal Fellows

4
注意:String.Format“使用” Int32.ToString(),因此上述所有内容也适用于String.Format。
Maris B.

29

根据随机抽样的整数进行的测试,Windows上安装的所有352种文化(CultureTypes.InstalledWin32Cultures)的给出了相同的结果。

Daniel正确地指出,自定义区域性可以对负数使用不同的前缀,但是我怀疑有人曾经偶然使用过此功能。

我想.NET开发人员这样做是为了与float和其他类型保持一致。他们还期待什么?

> int.MaxValue.ToString(CultureInfo.AncientRome)
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM....

12
我对《守则》感到极大的不安,好像数以百万计的家庭作业突然惊恐地哭了起来,并突然变得沉默了。
托马斯·兰斯顿

你实际上是要我去那里。叹。
ErikE 2015年

3
实际上,+ 0是古罗马人对大数的使用更为通用的系统-knowtheromans.co.uk/img/Roman-Numerals-Large-Numbers.png;也不够jQuery !!!

为+1 CultureInfo.AncientRome。我们也需要CultureInfo.AncientBabylon,但您需要安装楔形文字的字体才能使用它。
reirab

1
@vaxquis链接现在已失效,请参见存档的图像
布克

4

有点奇怪; 我本来希望50.ToString(CultureInfo.CreateSpecificCulture(“ ar-AE”))返回“ ٥٠”,但事实并非如此。

我只是看了一下,问题似乎是NumberFormatInfo.DigitSubstitution实际上没有实现

DigitSubstitution属性保留供将来使用。当前,当前NumberFormatInfo对象的解析或格式化操作中均未使用它。

因此,尽管存在枚举System.Globalization.DigitShapes,但实际上并未在IFormatProvider的NumberFormatInfo位中实现。


3

是。这取决于当前的文化。从MSDN文档

返回值使用通用数字格式说明符(“ G”)和当前区域性的NumberFormatInfo对象格式化。

重点矿

Resharper最有可能希望您明确说明您打算使用哪种文化。由于省略,它依赖于在不同计算机上执行时可能会改变的行为。


2
但是省略它会使其使用线程中的当前区域性,这很可能是您想要的。(如果用户切换语言,你输出到其他城市)
马格纳斯

4
@Magnus,仅在格式化字符串进行显示时才需要当前的区域性。如果您要对其进行格式化以实现持久性(例如,以XML / JSON / CSV /任何格式),那么最好使用不变式区域性。
乔·怀特

@JoeWhite xml / json消毒器仍然不会使用区域性。但是是的,如果您想使用ToString()某个地方将双精度型保存为字符串并将其转换回双精度型,则最好使用不变文化。但是我要说,有99%的时间不是您想要做的。
Magnus

0

我会说不,但是在检查MSDN Int32.ToString()时,这是这样的:

返回值使用通用数字格式说明符(“ G”)和当前区域性的NumberFormatInfo对象格式化。

所以有一个惊喜。

问题应该是为什么当前的《 Reshaper》不建议这样做?


-1

编译器(不必要地)警告我们有关它的信息可能以某种方式转换为字符串,而不是我们期望的那样。例如:

int i = 1;
Console.WriteLine("i.ToString='{0}'", i.ToString());

我们都希望它返回为“ 1”,但不能保证100%,因为.ToString()方法受当前线程区域性的影响。它声称它可以返回“ 1.00”或类似的值,但是我用一个非常小的代码对其进行了测试:

foreach(CultureInfo ci In System.Globalization.CultureInfo.GetCultures(CultureTypes.AllCultures) {
        Console.WriteLine("RESULT='{0}' CultureCode: {1} EnglishName:{2}", i.ToString(ci), ci.Name, ci.EnglishName);
        if (!i.ToString(ci).Equals("1"))
            throw new FormatException()
}

该代码从未返回任何错误。因此,它实际上从不返回“ 1”以外的任何东西。

只要这个世界上会有一个使用全新的本机超级怪兽语言的新国家,实际上将整数拼写为“ 1.00”,我们可以毫无疑问地继续使用.ToString()。

干杯!

输出为:


1
听起来您进行的测试与Panic上校的回答中已经描述的相同。
乔·怀特

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.