2016-03-02 12 views
25

In C#:Int32.Parse vs Single.Parse - ("1,234") e ("1,2,3,4"). Perché i tipi int e floating point analizzano i caratteri separatori in modo diverso?

Questo getta una FormatException, che sembra non dovrebbe:

Int32.Parse("1,234"); 

Questo non lo fa, che sembra normale:

Single.Parse("1,234"); 

E sorprendentemente, questo analizza solo fine:

Single.Parse("1,2,3,4"); //Returns 1234 

La mia cultura locale è EN-US, quindi , è il carattere di separazione di migliaia predefinito.

domanda principale: Perché l'incoerenza?

Inoltre: Perché funziona Parse("1,2,3,4")? Sembra che stia rimuovendo tutte le istanze del char del separatore locale prima dell'analisi. So che ci sarebbe un sovraccarico extra di runtime in un controllo regex o qualcosa del genere, ma quando il letterale numerico "1,2,3,4" non dovrebbe essere un refuso?


correlati: C# Decimal.Parse issue with commas

+0

Interessante .. 'Single.Parse (" 1,2,3,4 ", NumberFormatInfo.InvariantInfo);' restituisce anche '1234'. – Sinatr

+9

Qui non c'è incoerenza. 'Int32.Parse()' imposta di default 'NumberStyles.Integer' per il suo secondo argomento, che non supporta il separatore delle migliaia. D'altra parte, 'Single.Parse()' imposta di default 'NumberStyles.Float | NumberStyles.AllowThousands', che, beh, consente migliaia di separatori. Vedere la sezione Note in [la documentazione per quest'ultimo] (https://msdn.microsoft.com/en-us/library/2thct5cb.aspx). –

+0

@ FrédéricHamidi, il problema è il terzo esempio. Non c'è bisogno di spiegare prima o seconda. Puoi spiegare perché '" 1,2,3,4 "' è analizzato come valore '1234'? Ora sono spaventato per i miei campi di input dell'utente .. per tutti loro! – Sinatr

risposta

12

Secondo MSDN:

La s parametro contiene un certo numero di forma:

[ws] [segno] cifre [ws]


Il parametro s viene interpretato utilizzando lo stile NumberStyles.Integer. Oltre alle cifre decimali, sono consentiti solo gli spazi iniziali e finali e un segno iniziale.

Ecco, NumberStyles.Integer Non consente il metodo Parse utilizzare il separatore delle migliaia, mentre Single.Parse utilizza per default NumberStyles.Float e NumberStyles.AllowThousands. È possibile modificare questo comportamento specifiying secondo argomento, come NumberStyles:

Int32.Parse("1,234", NumberStyles.AllowThousands); //works 

Single.Parse ignora il raggruppamento e non usa culturospecifico NumberGroupSizes affatto, e solo determina se il carattere è un separatore di gruppo o decimale. Le dimensioni del gruppo vengono utilizzate solo quando si formattano i numeri.

2

mio è es-ES su questi. è il carattere predefinito di separatore di migliaia e "," il carattere separato tra int e doppio Quindi qualsiasi analisi come "1.2.3.4" mi restituisce "123,40" (123.40 negli Stati Uniti) Se inserisco ". " prima del "," come "123,4.3" dà l'errore ma, allo stesso modo delle domande, se metto "1.2.3.4" mi dà "1234" Quindi, potrebbe essere una funzionalità di .net si.

11

Per il primo caso , da Microsoft Source Code Reference, per default Int32.Parse implementa NumberStyles.Integer ma non NumberStyles.AllowThousands

public static int Parse(String s) { 
    return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); 
} 

Così qualsiasi virgola separatore non è consentito. Questo:

Int32.Parse("1,234"); 

o

Int32.Parse("1.234"); 

saranno entrambi essere sbagliato. In qualsiasi coltura.

Per risolvere il problema, NumberStyles.AllowThousands deve essere aggiunto al NumberStyles che permetterà "1.234" per essere analizzato in EN-US cultura:

Int32.Parse("1,234", NumberStyles.Integer | NumberStyles.AllowThousands); 

Ma

Int32.Parse("1.234", NumberStyles.Integer | NumberStyles.AllowThousands); 

sarà ancora throw un Exception.


Per il secondo caso, secondo Microsoft Code Source Reference, lo stile predefinito per Single.Parse è:

public static float Parse(String s) { 
    return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo); 
} 

che permette thousands separator. E "," è riconosciuto come separatore delle migliaia in EN-US cultura, per Single.Parse e quindi si ottiene il secondo caso analizzato correttamente

Single.Parse("1,234"); //OK 

E ovviamente "1.234" sarà anche corretto, se non che "" non è riconosciuto come separatore delle migliaia ma separatore decimale.


Per quanto riguarda il terzo caso , Internally, Single.Parse chiama TryStringToNumber, e Parse.Number che sarebbe semplicemente ignorare i separatori delle migliaia. Così si ottiene:

Single.Parse("1,2,3,4"); //Returns 1234 

Perché è equivalente

Single.Parse("1234"); //Returns 1234 
+1

L'OP non dice 'Int32.Parse (" 1,234 ");' tuttavia lancia un 'FormatException'? – weston

Problemi correlati