我正在从旧的MFC GUI迁移到C#。
当我遇到将字符串转换为整数类型的意外异常时,我正在构建基于表单的GUI。我认为它的工作原理与将字符串转换为double相同。
string str = "1,000";
double dthou = Convert.ToDouble(str); // OK
int ithou = Convert.ToInt32(str); // raises an exception
转换为double会给出正确的值:1000.0。 对于int转换,我能够得到一个解决方案:Convert.ToInt32() a string with Commas。
但我很好奇这背后是否有任何理由。 或者,我错过了什么?
我能够找到类似但不完全重复的问题: Number parsing weirdness
[编辑]了解了文化问题。
我处于一种文化冲击中,因为到目前为止,在韩国,浮点数和整数都用“,”表示,对于数千组和“。”。对于小数点(至少在现实世界中,在韩国,我的意思是,我认为......)。 我想我将不得不接受MS Visual Studio的当前设置并继续。
睡过这个问题之后[EDIT2]。
我认为这更多是对格式化字符串的不一致处理。 ToDouble接受带有千位分隔符的字符串(在我的文化中,逗号),但ToInt32没有。如果ToDouble
是float | allowThousands
,那么为什么ToInt32
integer | allowThousands
不是{{1}}就是我要问的。
答案 0 :(得分:3)
对于双重转换,有两种可能性:
,
是数字组分隔符。因此转换成功并返回值1000
。,
用作小数点分隔符。再次转换为浮点成功,但这次返回1
。要转换为整数,"1,000"
根本不是整数。鉴于您的命名,我怀疑,
是一个数字组分隔符。并期望ToInt32()
以这种方式对待它。但是ToInt32()
不接受数字组分隔符。 ToInt32()
的有效字符为0
到9
,-
或+
的可选符号前缀以及前导或尾随空格。
答案 1 :(得分:2)
在你的个人资料中,它说你来自韩国。这就是为什么我认为你现在的文化是ko-KR
。 (还有你said。)
它是NumberDecimalSeparator
.
但是NumberGroupSeparator
是,
您的Convert.ToDouble
有效并假设您的,
是千位分隔符,而不是十进制分隔符。这就是为什么您的dthou
将1000
而不是1
。
Convert.ToInt32(string)
明确使用Int32.Parse(string, CultureInfo.CurrentCulture)
,此方法implemented喜欢;
public static int Parse(String s, IFormatProvider provider)
{
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
正如您所看到的,此方法使用NumberStyles.Integer
作为默认值。这就是为什么你的字符串只能成功地解析它们中的一个;
由于你的字符串有数千个分隔符或十进制分隔符(这取决于你用过的字符串),这个方法会引发异常。
除此之外,您可以使用Int32.Parse(String, NumberStyles, IFormatProvider)
overload来指定NumberStyles
NumberStyles.AllowDecimalPoint
或NumberStyles.AllowThousands
作为一个例子;
string str = "1,000";
int ithou = Int32.Parse(str, NumberStyles.AllowThousands,
new CultureInfo("ko-KR"));
Console.WriteLine(ithou); // Prints 1000
如果您希望获得1
,可以使用CultureInfo.Clone
method到您的文化中并设置NumberDecimalSeparator
和NumberGroupSeparator
属性,例如;
string str = "1,000";
CultureInfo c = (CultureInfo)CultureInfo.GetCultureInfo("ko-KR").Clone();
c.NumberFormat.NumberDecimalSeparator = ",";
c.NumberFormat.NumberGroupSeparator = ".";
int dthou = Int32.Parse(str, NumberStyles.AllowDecimalPoint, c);
Console.WriteLine(dthou ); // Prints 1
我不认为这是一个文化问题。这是不一致的处理 格式化字符串。 ToDouble用逗号接受字符串,但是 ToInt32没有。这就像回到原来的问题, 但是不能实现ToInt32来接受逗号就好了 ToDouble功能?
哦,亲爱的朋友,你还在想错...
在你的情况下,一切都是文化问题。没有这样的事情“ Convert.ToDouble()
接受带逗号的字符串,但Convert.ToInt32()
不”。
让我们再看一下这些方法是如何实现的。
Convert.ToDouble(string)
明确使用Double.Parse(value, CultureInfo.CurrentCulture)
,implemented就像;
public static double Parse(String s, IFormatProvider provider)
{
return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}
使用此NumberStyles.Float| NumberStyles.AllowThousands
,您可以在代码中同时使用小数点或千位分隔符,但,
是您的文化NumberGroupSeparator
而不是NumberDecimalSeparator
。这就是为什么你的字符串将被解析为数千个seperetor。 没有这样的东西Convert.ToDouble使用带逗号的字符串。它可以使用您当前的文化NumberDecimalSeparator
或NumberGroupSeparator
取决于您的字符串所具有的字符。如果两者相等,NumberDecimalSeparator
将占主导地位并将被使用。
Convert.ToInt32(string)
明确使用Int32.Parse(string, CultureInfo.CurrentCulture)
,而implemented就像;
public static int Parse(String s, IFormatProvider provider)
{
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
正如我之前所说,NumberStyles.Integer
允许你的三个字符串;领先的白色空间,尾随白色空间和领先的正面或负面标志。如果您的字符串包含小数点分隔符或千位分隔符,则无论是逗号还是点,都无法解析。
我之前告诉过你。但是无法实现ToInt32以接受逗号 ToDouble功能?
Convert.ToInt32
没有重载需要NumberStyles
作为参数。您可以使用Int32.Parse(String, NumberStyles, IFormatProvider)
overload指定NumberStyles
枚举来解析小数点分隔符或千位分隔符。
答案 2 :(得分:0)
在英国文化中,十进制符号是"。" 。在瑞典文化中,十进制的叹息是",#34;。无数的标志可以是" ",","或"。"。这就是为什么当小数符号与其指定的文化不同时C#抛出异常的原因。