Int32.Parse与Single.Parse - ("1,234")和("1,2,3,4").为什么int和浮点类型以不同方式解析分隔符字符?

Jam*_*aix 25 .net c# floating-point int parsing

在C#中:

抛出一个FormatException,似乎不应该:

Int32.Parse("1,234");
Run Code Online (Sandbox Code Playgroud)

这不,这似乎是正常的:

Single.Parse("1,234");
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,这解析得很好:

Single.Parse("1,2,3,4"); //Returns 1234
Run Code Online (Sandbox Code Playgroud)

我的本地文化是EN-US,,默认的千位分隔符char也是如此.

主要问题:为什么不一致?

另外:为什么Parse("1,2,3,4")工作?它似乎只是在解析之前删除本地分隔符char的所有实例.我知道在正则表达式检查或类似的东西中会有额外的运行时开销,但什么时候数字文字"1,2,3,4"不是拼写错误?


相关: C#Decimal.Parse问题用逗号

Ill*_*ack 12

根据MSDN:

s参数包含以下形式的数字:

[WS] [符号]数字[WS]


小号参数使用NumberStyles.Integer风格解释.除十进制数字外,只允许前导和尾随空格以及前导符号.

就是这样,NumberStyles.Integer不允许Parse方法使用千位分隔符,而Single.Parse默认使用NumberStyles.FloatNumberStyles.AllowThousands.您可以通过将第二个参数指定为NumberStyles来更改此行为:

Int32.Parse("1,234", NumberStyles.AllowThousands); //works
Run Code Online (Sandbox Code Playgroud)

Single.Parse忽略分组,根本不使用特定于文化的NumberGroupSizes,并且仅确定该字符是组还是小数分隔符.组大小仅在格式化数字时使用.


Ian*_*Ian 11

对于第一种情况,从Microsoft源代码参考,默认情况下Int32.Parse实现NumberStyles.Integer但不实现NumberStyles.AllowThousands

public static int Parse(String s) {
    return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
Run Code Online (Sandbox Code Playgroud)

因此不允许使用任何逗号分隔符.这个:

Int32.Parse("1,234");
Run Code Online (Sandbox Code Playgroud)

要么

Int32.Parse("1.234"); 
Run Code Online (Sandbox Code Playgroud)

两者都错了.在任何文化中.

要修复它,NumberStyles.AllowThousands必须添加到NumberStyles将允许在EN-US文化中解析"1,234" :

Int32.Parse("1,234", NumberStyles.Integer | NumberStyles.AllowThousands);
Run Code Online (Sandbox Code Playgroud)

Int32.Parse("1.234", NumberStyles.Integer | NumberStyles.AllowThousands);
Run Code Online (Sandbox Code Playgroud)

还是会throwException.


对于第二种情况,根据Microsoft Code Source Reference,默认样式为Single.Parse:

public static float Parse(String s) {
    return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}
Run Code Online (Sandbox Code Playgroud)

这允许千位分隔符.并且","EN-US文化中被认为是千分隔符Single.Parse,因此您可以正确解析第二种情况

Single.Parse("1,234"); //OK
Run Code Online (Sandbox Code Playgroud)

显然"1.234"也是正确的,除了"." 不被识别为千位分隔符而是小数分隔符.


至于第三种情况,内部,Single.Parse调用TryStringToNumberParse.Number,它们会忽略千位分隔符.这样你得到:

Single.Parse("1,2,3,4"); //Returns 1234 
Run Code Online (Sandbox Code Playgroud)

因为它相当于

Single.Parse("1234"); //Returns 1234 
Run Code Online (Sandbox Code Playgroud)