C#Decimal.Parse问题用逗号

Edu*_*coz 21 c# parsing decimal

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

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

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

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

谢谢!

Ori*_*rds 14

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

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

Decimal.Parse("1,2,3,4", NumberStyles.Number ^ NumberStyles.AllowThousands)
Run Code Online (Sandbox Code Playgroud)

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

  • 我不认为那是他想要的。我认为他希望它认为“1,200”有效,而不是“1,2,0,0”......但可能是错误的。 (2认同)
  • 不是,约书亚.在en-US语言环境中,Decimal.Parse将"123,40"转换为12340.00,而不是123.40.该行为与其他语言环境一致.. (2认同)

Edu*_*coz 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);
    }
Run Code Online (Sandbox Code Playgroud)

这是一个显示它工作的测试(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;

    }
Run Code Online (Sandbox Code Playgroud)

  • 此外,.Net确实支持货币解析.您只需要传递NumberStyles选项的货币规则(即NumberStyles.Currency).它对分组器的分组也有更自由的解释. (2认同)