这是我的问题(对于en-US):
Decimal.Parse("1,2,3,4")
返回1234,而不是抛出InvalidFormatException。
大多数Windows应用程序(Excel en-US)不会丢弃千位分隔符,也不会将该值视为十进制数。其他语言也会出现同样的问题(尽管字符不同)。
是否有其他十进制解析库可以解决这个问题?
谢谢!
答案 0 :(得分:14)
允许数千,因为NumberStyles
(Decimal.Parse
)使用的默认NumberStyles.Number
值包含NumberStyles.AllowThousands
。
如果你想禁止千位分隔符,你可以删除那个标志,如下所示:
Decimal.Parse("1,2,3,4", NumberStyles.Number ^ NumberStyles.AllowThousands)
(上面的代码会抛出InvalidFormatException
,这就是你想要的,对吗?)
答案 1 :(得分:10)
我最终不得不编写代码来手动验证货币。就个人而言,对于一个以内置所有全球化内容而自豪的框架,令人惊讶的.NET没有任何东西可以解决这个问题。
我的解决方案如下。它适用于框架中的所有语言环境。它不支持负数,正如Orion在下面指出的那样。你们觉得怎么样?
public static bool TryParseCurrency(string value, out decimal result)
{
result = 0;
const int maxCount = 100;
if (String.IsNullOrEmpty(value))
return false;
const string decimalNumberPattern = @"^\-?[0-9]{{1,{4}}}(\{0}[0-9]{{{2}}})*(\{0}[0-9]{{{3}}})*(\{1}[0-9]+)*$";
NumberFormatInfo format = CultureInfo.CurrentCulture.NumberFormat;
int secondaryGroupSize = format.CurrencyGroupSizes.Length > 1
? format.CurrencyGroupSizes[1]
: format.CurrencyGroupSizes[0];
var r = new Regex(String.Format(decimalNumberPattern
, format.CurrencyGroupSeparator==" " ? "s" : format.CurrencyGroupSeparator
, format.CurrencyDecimalSeparator
, secondaryGroupSize
, format.CurrencyGroupSizes[0]
, maxCount), RegexOptions.Compiled | RegexOptions.CultureInvariant);
return !r.IsMatch(value.Trim()) ? false : Decimal.TryParse(value, NumberStyles.Any, CultureInfo.CurrentCulture, out result);
}
这是一个显示它正常工作的测试(nUnit):
[Test]
public void TestCurrencyStrictParsingInAllLocales()
{
var originalCulture = CultureInfo.CurrentCulture;
var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
const decimal originalNumber = 12345678.98m;
foreach(var culture in cultures)
{
var stringValue = originalNumber.ToCurrencyWithoutSymbolFormat();
decimal resultNumber = 0;
Assert.IsTrue(DecimalUtils.TryParseCurrency(stringValue, out resultNumber));
Assert.AreEqual(originalNumber, resultNumber);
}
System.Threading.Thread.CurrentThread.CurrentCulture = originalCulture;
}
答案 2 :(得分:1)
您可以在两阶段过程中执行此操作。首先,您可以使用CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator
和CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes
中的信息验证千位分隔符,如果未通过则抛出异常,然后将该数字传递到Decimal.Parse()
;
答案 3 :(得分:0)
这是微软从未解决的常见问题。 所以,我不明白为什么1,2,3.00(例如英国文化)是有效的! 如果测试未通过,您需要构建一个算法来检查组大小并返回false / exception(如失败的double.parse)。 我在mvc应用程序中遇到了类似的问题,在验证器中构建并不接受数千个。所以我用自定义覆盖它,使用double / decimal / float.parse,但添加了一个逻辑来验证小组规模。
如果你想读我的解决方案(它用于我的mvc自定义验证器,但你可以使用它有一个更好的双/十进制/ float.parse通用验证器)去这里 https://stackoverflow.com/a/41916721/3930528