C#Decimal.Parse问题用逗号

这是我的问题(对于en-US):

Decimal.Parse("1,2,3,4")返回1234,而不是抛出InvalidFormatException。

大多数Windows应用程序(Excel en-US)不会删除千位分隔符,也不会将该值视为十进制数。 其他语言也会出现同样的问题(尽管字符不同)。

还有其他十进制解析库可以解决这个问题吗?

谢谢!

它允许数千,因为Decimal.ParseNumberStyles.Number )使用的默认NumberStyles值包括NumberStyles.AllowThousands

如果你想禁止数千个分隔符,你可以删除那个标志,如下所示:

 Decimal.Parse("1,2,3,4", NumberStyles.Number ^ NumberStyles.AllowThousands) 

(上面的代码会抛出一个InvalidFormatException ,这就是你想要的,对吧?)

我最终不得不编写代码来手动validation货币。 就个人而言,对于一个以内置所有全球化内容而自豪的框架来说,令人惊讶的是.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; } 

您可以在两个阶段中完成此操作。 首先,您可以使用CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparatorCultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes的信息validation千位分隔符,如果它未通过则抛出exception,然后将该数字传递给Decimal.Parse() ;

这是微软从未解决的常见问题。 所以,我不明白为什么1,2,3.00(例如英国文化)是有效的! 如果未通过测试,则需要构建一个算法来检查组大小并返回false / exception(如失败的double.parse)。 我在mvc应用程序中遇到了类似的问题,在validation器中构建不接受数千个。所以我用自定义覆盖它,使用double / decimal / float.parse,但添加逻辑来validation组大小。

如果你想读我的解决方案(它用于我的mvc自定义validation器,但你可以使用它有一个更好的双/十进制/ float.parse通用validation器)去这里https://stackoverflow.com/a/41916721/3930528