【发布时间】:2017-01-29 16:55:58
【问题描述】:
有没有办法让 C# TryParse() 函数更...严格一点?
现在,如果你传入一个包含数字、正确的十进制和千位分隔符的字符串,它通常似乎只是接受它们,即使格式没有意义,例如:123''345'678
如果号码格式不正确,我正在寻找一种方法让TryParse 不会成功。
所以,我在苏黎世,如果我这样做:
decimal exampleNumber = 1234567.89m;
Trace.WriteLine(string.Format("Value {0} gets formatted as: \"{1:N}\"", exampleNumber, exampleNumber));
...然后,根据我的区域设置,我得到了这个...
Value 1234567.89 gets formatted as: "1'234'567.89"
所以您可以看到,对于我所在的地区,小数点字符是句号,千位分隔符是撇号。
现在,让我们创建一个简单的函数来测试是否可以将string 解析为decimal:
private void ParseTest(string str)
{
decimal val = 0;
if (decimal.TryParse(str, out val))
Trace.WriteLine(string.Format("Parsed \"{0}\" as {1}", str, val));
else
Trace.WriteLine(string.Format("Couldn't parse: \"{0}\"", str));
}
好的,让我们用几个字符串来调用这个函数。
您认为以下哪些字符串会被此函数成功解析?
以下是我得到的结果:
ParseTest("123345.67"); // 1. Parsed "123345.67" as 123345.67
ParseTest("123'345.67"); // 2. Parsed "123'345.67" as 123345.67
ParseTest("123'345'6.78"); // 3. Parsed "123'345'6.78" as 1233456.78
ParseTest("1''23'345'678"); // 4. Parsed "1''23'345'678" as 123345678
ParseTest("'1''23'345'678"); // 5. Couldn't parse: "'1''23'345'678"
ParseTest("123''345'678"); // 6. Parsed "123''345'678" as 123345678
ParseTest("123'4'5'6.7.89"); // 7. Couldn't parse: "123'4'5'6.7.89"
ParseTest("'12'3'45'678"); // 8. Couldn't parse: "'12'3'45'678"
我想你能明白我的意思。
对我来说,只有前两个字符串应该已成功解析。其他的应该都失败了,因为它们在千位分隔符后没有 3 位数字,或者两个撇号在一起。
即使我将ParseTest 更改为更具体一点,结果也完全相同。 (例如,它很乐意接受“123''345'678”作为有效的小数。)
private void ParseTest(string str)
{
decimal val = 0;
var styles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);
if (decimal.TryParse(str, styles, CultureInfo.CurrentCulture, out val))
Trace.WriteLine(string.Format("Parsed \"{0}\" as {1}", str, val));
else
Trace.WriteLine(string.Format("Couldn't parse: \"{0}\"", str));
}
那么,有没有一种直接的方法不允许格式错误的字符串被TryParse 接受?
更新
感谢所有建议。
也许我应该澄清一下:我正在寻找的是这些字符串中的前两个有效,但第三个被拒绝。
ParseTest("123345.67");
ParseTest("123'456.67");
ParseTest("12'345'6.7");
肯定有一种方法可以使用“NumberStyles.AllowThousands”,因此它可以选择允许千位分隔符,但要确保数字格式是否有意义?
现在,如果我使用这个:
if (decimal.TryParse(str, styles, CultureInfo.CurrentCulture, out val))
我得到了这些结果:
Parsed "123345.67" as 123345.67
Parsed "123'456.67" as 123456.67
Parsed "12'345'6.7" as 123456.7
如果我使用这个:
if (decimal.TryParse(str, styles, CultureInfo.InvariantCulture, out val))
我得到了这些结果:
Parsed "123345.67" as 123345.67
Couldn't parse: "123'456.67"
Couldn't parse: "12'345'6.7"
这是我的问题...无论 CultureInfo 设置如何,都应该拒绝第三个字符串,而接受前两个。
【问题讨论】:
-
您需要接受有效千位分隔符吗?如果没有,请不要使用 AllowThousands...
-
看起来您需要单独的正则表达式验证。
-
老实说,当您在
123''345'678示例中分配正确的属性时,我很惊讶相邻的数千个分隔符被成功解析甚至。但在这种情况下,也许您只需将NumberGroupSizes属性分配为{3, 3, 0}。我不知道。 -
所以你的文化是
de-CH,不是吗?然后我们可以通过添加System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("de-CH");来重现它 -
@PaulKienitz:想到正则表达式用于此目的,我不寒而栗