有没有办法让C#TryParse()函数更严格一些?
现在,如果你传入一个包含数字,正确的十进制和千位分隔符的字符串,它通常似乎接受它们,即使格式没有意义,例如: 123''345'678
如果数字格式不正确,我正在寻找一种TryParse 不成功的方法.
所以,我的总部设在苏黎世,如果我这样做:
decimal exampleNumber = 1234567.89m;
Trace.WriteLine(string.Format("Value {0} gets formatted as: \"{1:N}\"", exampleNumber, exampleNumber));
Run Code Online (Sandbox Code Playgroud)
...然后,根据我的区域设置,我得到了......
Value 1234567.89 gets formatted as: "1'234'567.89"
Run Code Online (Sandbox Code Playgroud)
所以你可以看到,对于我的区域,小数位字符是一个句号,千分隔符是一个撇号.
现在,让我们创建一个简单的函数来测试是否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));
}
Run Code Online (Sandbox Code Playgroud)
好吧,让我们用几个字符串来调用这个函数.
您认为以下哪个字符串可以被此函数成功解析?
以下是我得到的结果:
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"
Run Code Online (Sandbox Code Playgroud)
我想你可以看到我的观点.
对我来说,只有前两个字符串才能成功解析.其他人应该都失败了,因为他们在千分之后没有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));
}
Run Code Online (Sandbox Code Playgroud)
那么,是否有一种直接的方法可以不允许接受格式错误的字符串TryParse?
更新
感谢所有的建议.
也许我应该澄清:我正在寻找的是前两个字符串是有效的,但第三个被拒绝.
ParseTest("123345.67");
ParseTest("123'456.67");
ParseTest("12'345'6.7");
Run Code Online (Sandbox Code Playgroud)
当然,必须有使用"的方式NumberStyles.AllowThousands",因此它可以选择性地允许千分隔符,但要确保数字格式没有意义?
现在,如果我使用这个:
if (decimal.TryParse(str, styles, CultureInfo.CurrentCulture, out val))
Run Code Online (Sandbox Code Playgroud)
我得到这些结果:
Parsed "123345.67" as 123345.67
Parsed "123'456.67" as 123456.67
Parsed "12'345'6.7" as 123456.7
Run Code Online (Sandbox Code Playgroud)
如果我使用这个:
if (decimal.TryParse(str, styles, CultureInfo.InvariantCulture, out val))
Run Code Online (Sandbox Code Playgroud)
我得到这些结果:
Parsed "123345.67" as 123345.67
Couldn't parse: "123'456.67"
Couldn't parse: "12'345'6.7"
Run Code Online (Sandbox Code Playgroud)
这是我的问题......无论CultureInfo设置如何,都应拒绝第三个字符串,并接受前两个字符串.
这是因为解析只是跳过NumberFormatInfo.NumberGroupSeparator字符串并完全忽略该NumberFormatInfo.NumberGroupSizes属性。但是,您可以实现这样的验证:
static bool ValidateNumberGroups(string value, CultureInfo culture)
{
string[] parts = value.Split(new string[] { culture.NumberFormat.NumberGroupSeparator }, StringSplitOptions.None);
foreach (string part in parts)
{
int length = part.Length;
if (culture.NumberFormat.NumberGroupSizes.Contains(length) == false)
{
return false;
}
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
正如 MSDN所说,它仍然不完全完美:
数组的第一个元素定义紧邻 NumberDecimalSeparator 左侧的最低有效数字组中的元素数量。每个后续元素均指前一组左侧的下一个有效数字组。如果数组的最后一个元素不为 0,则剩余的数字根据数组的最后一个元素进行分组。如果最后一个元素为 0,则剩余数字不分组。
例如,如果数组包含 { 3, 4, 5 },则数字的分组类似于“55,55555,55555,55555,4444,333.00”。如果数组包含 { 3, 4, 0 },则数字的分组类似于“55555555555555555,4444,333.00”。
但你现在可以明白这一点了。
| 归档时间: |
|
| 查看次数: |
965 次 |
| 最近记录: |