开发者

C# decimal.Parse behaviour

Short question:

Why are these '.....' valid for parsing a decimal in .NET (C#):

decimal res = decimal.Parse("8......15");  // returns 815
decimal res = decimal.Parse("8...15");     // returns 815
decimal res = decimal.Parse("8..15");      // returns 815

What's the开发者_如何学编程 reason for this?


It fails for me. Are you by any chance in a culture where "." is the thousands separator and "," is the decimal point? Decimal.Parse (and similar calls) use the thread's current culture by default. Whether that is a good thing or not is debatable, but irrelevant to actual behaviour :)

Try specifying CultureInfo.InvariantCulture in the decimal.Parse call:

decimal res = decimal.Parse("8......15", CultureInfo.InvariantCulture);

I believe that will behave as you expected.


I would imagine it's because the parser doesn't actually care about group separators - they are irrelevant to the process of converting a string to a decimal.

We call them thousands separators, but they're really not. They are group separators - you could split every 3 digits, every 10 digits, every 1 digit, so why not every 0 digits?

Interestingly, the code has changed for .NET 4 - this is the relevant output from Reflector for me:

else
{
    if (((currencySymbol == null) || 
         ((chPtr2 = MatchChars(p, currencySymbol)) == null)) && 
        ((ansiCurrencySymbol == null) || 
         ((chPtr2 = MatchChars(p, ansiCurrencySymbol)) == null)))
    {
        break;
    }
    num |= 0x20;
    currencySymbol = null;
    ansiCurrencySymbol = null;
    p = chPtr2 - 1;
}


I don’t know why, but I know how it works (decimal parser code part see below). I think last else if just turn on point flag and skip all points.

    while (true)
{
    if (((ch >= '0') && (ch <= '9')) || (((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None) && (((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F')))))
    {
        //Here goes some code...
    }
    else if ((((options & NumberStyles.AllowDecimalPoint) != NumberStyles.None) && ((num & 0x10) == 0)) 
    && (((chPtr2 = MatchChars(p, currencyDecimalSeparator)) != null) || ((flag && ((num & 0x20) == 0)) 
    && ((chPtr2 = MatchChars(p, numberDecimalSeparator)) != null))))
    {
        num |= 0x10;
        p = chPtr2 - 1;
    }
}

Use Reflector tool to investigate all code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜