2011-01-13 30 views
7

pregunta corta:C# decimal.Parse comportamiento

¿Por qué son estos '.....' válido para analizar un decimal en .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 

¿Cuál es la razón de ¿esta?

+0

he comprobarlo en .NET4.0. Se plantea una excepción de formato – HuBeZa

+0

¿Qué cultura estás usando? Esas cadenas no se pueden analizar usando mi cultura actual o la cultura invariante. – LukeH

+0

Creo que es una pereza de programador. No he visto un lugar que use miles de separadores sin mucha importancia. – HuBeZa

Respuesta

18

No funciona para mí. ¿Estás por casualidad en una cultura en la que "." es el separador de miles y "," es el punto decimal? Decimal.Parse (y llamadas similares) utilizan la cultura actual del hilo de forma predeterminada. Incluso si esto es bueno o no es discutible, pero irrelevante para el comportamiento real :)

intente especificar CultureInfo.InvariantCulture en la llamada decimal.Parse:

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

Creo que se comportará como se esperaba.

+0

Creo que has golpeado el clavo en la cabeza. Se analiza correctamente si utiliza la cultura 'de-DE', por ejemplo. – LukeH

+0

'es-ES' a. Qué cultura más extraña – HuBeZa

+0

De hecho. Mi CurrentCulture es "nl-BE", NumberDecimalSeparator = "," y NumberGroupSeparator = "." Gracias! Pero es bastante extraño que permitan tal notación. – juFo

1

No sé por qué, pero sé cómo funciona (parte del código del analizador decimal ver a continuación). Creo que lo último si solo enciendes el indicador de punto y saltas todos los puntos.

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; 
    } 
} 

Utilice la herramienta Reflector para investigar todo el código.

+0

¡Interesante! Es bueno ver ese código de parte sobre el HexSpecifier. – juFo

2

Me imagino que es porque al analizador en realidad no le importan los separadores de grupo, son irrelevantes para el proceso de conversión de una cadena a un decimal.

Los llamamos separadores de miles, pero en realidad no lo son. Son separadores de grupos: puede dividir cada 3 dígitos, cada 10 dígitos, cada 1 dígito, entonces ¿por qué no cada 0 dígitos?

Curiosamente, el código ha cambiado para .NET 4 - esta es la salida relevante de reflector para mí:

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; 
}