C# .NET Double.TryParse(num、format、cultureinfo、out)错误
背景:我最近有幸编写了一些代码,这些代码需要可靠地将字符串转换为双精度字符串。该功能也必须分发。i、 e.字符串存储在数据库中,需要在跨不同地区运行的多个代理上转换为数字。由于限制的原因,更改数据库模式是不可能的,我必须在遗留代码库中完成这项工作,并提供简单的升级路径,同时不破坏现有功能 我能够通过将存储的字符串规范化为不变格式并向编码中添加一个标志来解决这个问题,以指示值是规范化的,应该采用新路径还是非规范化(sp?)并采用传统路径 我忘了提到原始值是由最终用户输入的,必须在可接受的格式范围内。这意味着存储值可能有数字分组说明符,也可能没有数字分组说明符。显然,这是危险的,目前只针对beta版,而且很快就会对UI进行适当的国际化,以便发布适当的版本 也就是说,我认为我的转换代码应该能够处理数字分组字符是合理的,即使最终的规范化表单不包含它们。如果提供了正确的区域性格式,则Double.TryParse()和Double.ToString()在处理此问题时应该没有问题,并且转换代码可能会因为其他原因(是遗留代码!)而被重用 是.NET错误,因此我认为围绕国际化字符串到双精度转换代码编写一些单元测试是个好主意 我编写了两个主要测试(psuedo代码) 测试1:C# .NET Double.TryParse(num、format、cultureinfo、out)错误,c#,.net,vb.net,internationalization,double,C#,.net,Vb.net,Internationalization,Double,背景:我最近有幸编写了一些代码,这些代码需要可靠地将字符串转换为双精度字符串。该功能也必须分发。i、 e.字符串存储在数据库中,需要在跨不同地区运行的多个代理上转换为数字。由于限制的原因,更改数据库模式是不可能的,我必须在遗留代码库中完成这项工作,并提供简单的升级路径,同时不破坏现有功能 我能够通过将存储的字符串规范化为不变格式并向编码中添加一个标志来解决这个问题,以指示值是规范化的,应该采用新路径还是非规范化(sp?)并采用传统路径 我忘了提到原始值是由最终用户输入的,必须在可接受的格式范围内
Double testValue = 15000.05
foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures)
{
string testString = testValue.ToString(ci);
Assert.AreEqual(testValue, Convert(testString, ci));
}
测试2:
foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures)
{
string testString = testValue.ToString("N2", ci);
Assert.AreEqual(testValue, Convert(testString, ci));
}
相关转换代码(几乎一行一行):
对于测试,收集所有区域性代码的确切方法可能不同,Convert的方法签名不同,周围的代码和assert略有不同。
相关部分是.ToString(ci)和.ToString(“N2”,ci)。
对于en US,这些to版本将分别生成“15000.05”和“15000.05”。
此外,此代码在.NET版本2.0-4.5.2下运行,我们在各种相关版本下运行测试。它的行为在所有方面都是相同的(*可能需要再次检查,但这肯定是.NET 4.5.2中的行为)
测试1通过
Test2在以下5个区域性代码上失败:
- prs
- prs AF
- tzm
- tzm板条
- tzm Latn DZ
免责声明:我在VB.NET和C#之间切换,因此请原谅任何语法混淆。另外,我知道这个测试没有正确地解释“奇数”数字分组,就像印地语中1015000是10,15000。以下是他写的: “这里的问题是失败的文化,因为你有以下几点: 小数点分隔符为“,” 组分隔符为“” 货币小数点分隔符为“” 货币组分隔符为“,” 请注意,十进制分隔符与货币组分隔符相同。此外,组分隔符与货币十进制分隔符相同 现在,当您使用这种区域性设置数字格式时,您将得到字符串“15.000,05”。当您试图解析它时,您传递的是NumberStyles。Any表示该字符串可以是货币数字,也可以是十进制数字。这会使解析器在尝试解析字符时感到困惑。”。“因为它可以被视为货币十进制分隔符,也可以被视为组分隔符。解析器决定将其视为货币小数分隔符。然后解析器将继续运行,直到点击“,”并再次将其视为货币组分隔符。由于组分隔符不能位于十进制分隔符之后,解析器将无法解析字符串,并将从TryParse返回false(或从parse抛出异常) 要解决此问题,请从传递的NumberStyles中删除货币解析。i、 e
Double.TryParse(numString, NumberStyles.Any & (~NumberStyles.AllowCurrencySymbol), ci, out numParsed);
我将结束这一问题,但如果您有任何问题,请随时回答。”尚未进行进一步诊断,但我刚刚在dotnet github回购协议上提交了一个问题:
numOut = Double.Parse(numIn, ci)
Double.TryParse(numString, NumberStyles.Any & (~NumberStyles.AllowCurrencySymbol), ci, out numParsed);