Reputation: 2045
I am not sure how this is able to be parsed correctly in C# but I would like it to fail where the case where the comma is not separated every repeatable three value. Example: 1,123.23 should pass but 11,23.23 should fail in my sense. But the actual output is that tryparse seems to always return true regardless of where the position of comma is before decimal.
Edit: Answer with regex is being accepted since it is found that this is a bug. Thank you.
string price = "1,1,2,3.23";
decimal outputValue = 0;
var allowedStyles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);
if (Decimal.TryParse(price, allowedStyles, CultureInfo.GetCultureInfo("EN-us"), out outputValue))
{
Console.WriteLine("Pass");
}
Upvotes: 9
Views: 2926
Reputation: 35873
What you discovered is clearly a bug. I strongly recommend do not stuck here, instead implement a workaround. (and also apply KISS).
Unless this code part executed zillion ad zillion times in a high math algorithm's core or any other way is performance critical, here is a simple workaround.
(Supposing the strings are using ',' (comma) as thousand separator. (and they are not decimal separator as it could be some culture)):
price = price.Replace(",",""); // This will not change the value when comma is thousand separator.
// Go forward to parsing
Upvotes: 2
Reputation: 25023
You have two acceptable formats, so you can check if the number is parseable and, if so, check it is in an acceptable format:
string price = "1,123.23";
decimal outputValue = 0;
var allowedStyles = (NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands);
var cul = CultureInfo.GetCultureInfo("EN-us");
if (decimal.TryParse(price, allowedStyles, cul, out outputValue))
{
if (outputValue.ToString("N", cul) == price || outputValue.ToString("G", cul) == price)
{
Console.WriteLine("Pass");
}
}
Upvotes: 2
Reputation: 28111
As you noted NumberStyles.AllowThousands
doesn't enforce the comma to be on the correct place. So I think a regular expression can help you here:
Regex.IsMatch("11,23.23", "^[+-]?[0-9]{1,3}(,[0-9]{3})*(.[0-9]*)?$");
Upvotes: 4
Reputation: 894
I don't know if this helps but, yeah I think I should try. I think my answer is a little but straight forward, just if the concern is the format, I made it compare on a .ToString("format specified"); and compare it to your "price" string. Just my 2 cents.
string price = "1,1,2,3.23";
decimal priceParse = 0;
if (decimal.TryParse(price, out priceParse))
{
string shouldBeFormat = Convert.ToDecimal(priceParse).ToString("#,##0.00");
if (price == shouldBeFormat)
{
// your good
}
else
{
// no good
}
}
Upvotes: 3
Reputation: 3653
I ran a few different codes and i realized when you apply AllowThousands, the only constraint on the place of ',' is that it should be on the integer part of the number.
some results:
Upvotes: 1