C# Decimal.Parse 问题与逗号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/831727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Decimal.Parse issue with commas
提问by Eduardo Scoz
Here's my problem (for en-US):
这是我的问题(针对美国):
Decimal.Parse("1,2,3,4")
returns 1234, instead of throwing an InvalidFormatException.
Decimal.Parse("1,2,3,4")
返回 1234,而不是抛出 InvalidFormatException。
Most Windows applications (Excel en-US) do not drop the thousand separators and do not consider that value a decimal number. The same issue happens for other languages (although with different characters).
大多数 Windows 应用程序 (Excel en-US) 不会删除千位分隔符,并且不会将该值视为十进制数。其他语言也会出现同样的问题(尽管字符不同)。
Are there any other decimal parsing libraries out there that solve this issue?
有没有其他十进制解析库可以解决这个问题?
Thanks!
谢谢!
采纳答案by Eduardo Scoz
I ended up having to write the code to verify the currency manually. Personally, for a framework that prides itself for having all the globalization stuff built in, it's amazing .NET doesn't have anything to handle this.
我最终不得不编写代码来手动验证货币。就个人而言,对于一个以内置所有全球化内容而自豪的框架,令人惊讶的是 .NET 没有任何东西可以处理这个问题。
My solution is below. It works for all the locales in the framework. It doesn't support Negative numbers, as Orion pointed out below, though. What do you guys think?
我的解决方案如下。它适用于框架中的所有语言环境。不过,正如 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);
}
And here's one test to show it working (nUnit):
这是一个显示它工作的测试(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;
}
回答by Orion Edwards
It's allowing thousands, because the default NumberStyles
value used by Decimal.Parse
(NumberStyles.Number
) includes NumberStyles.AllowThousands
.
它允许数以千计,因为( )NumberStyles
使用的默认值包括.Decimal.Parse
NumberStyles.Number
NumberStyles.AllowThousands
If you want to disallow the thousands separators, you can just remove that flag, like this:
如果您想禁止使用千位分隔符,您可以删除该标志,如下所示:
Decimal.Parse("1,2,3,4", NumberStyles.Number ^ NumberStyles.AllowThousands)
(the above code will throw an InvalidFormatException
, which is what you want, right?)
(上面的代码会抛出一个InvalidFormatException
,这是你想要的,对吧?)
回答by Orion Adrian
You might be able to do this in a two-phase process. First you could verify the thousands separator using the information in the CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator
and CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes
throwing an exception if it doesn't pass and then pass the number into the Decimal.Parse()
;
您可以分两步完成此操作。首先,你可以使用的信息验证千位分隔符CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator
,并CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes
抛出一个异常,如果它没有通过,然后通过数字到Decimal.Parse()
;
回答by user3930528
It is a common issue never solved by microsoft. So, I don't understand why 1,2,3.00 (english culture for example) is valid! You need to build an algorith to examine group size and return false/exception(like a failed double.parse) if the test is not passed. I had a similar problem in a mvc application, which build in validator doesn't accept thousands..so i've overwrite it with a custom, using double/decimal/float.parse, but adding a logic to validate group size.
这是微软从未解决过的常见问题。所以,我不明白为什么 1,2,3.00(例如英语文化)是有效的!如果测试未通过,您需要构建一个算法来检查组大小并返回 false/异常(如失败的 double.parse)。我在 mvc 应用程序中遇到了类似的问题,它内置的验证器不接受数千..所以我用自定义覆盖了它,使用 double/decimal/float.parse,但添加了一个逻辑来验证组大小。
If you want read my solution (it is used for my mvc custom validator, but you can use it to have a better double/decimal/float.parse generic validator) go here https://stackoverflow.com/a/41916721/3930528
如果你想阅读我的解决方案(它用于我的 mvc 自定义验证器,但你可以使用它来获得更好的 double/decimal/float.parse 通用验证器)去这里 https://stackoverflow.com/a/41916721/3930528