2012-03-18 26 views
118

ho una stringa di testo in questo modo:Che cosa significa CultureInfo.InvariantCulture?

var foo = "FooBar"; 

Voglio dichiarare una seconda stringa denominata bar e rendere questo uguale a prima e quarto carattere del mio primo foo, quindi faccio questo modo:

var bar = foo[0].ToString() + foo[3].ToString(); 

questo funziona come previsto, ma ReSharper mi sta consigliando di mettere Culture.InvariantCulture dentro le mie parentesi, in modo da questa linea finisce in questo modo:

var bar = foo[0].ToString(CultureInfo.InvariantCulture) 
     + foo[3].ToString(CultureInfo.InvariantCulture); 

Cosa significa e influisce sul modo in cui viene eseguito il mio programma?

+1

Vai a questa domanda SO: http://stackoverflow.com/questions/8492449/is- int32-tostring-culture-specific – msigman

+3

Per coloro che cercano la risposta di 5 secondi: CultureInfo.InvariantCulture significa "Non mi interessa, non voglio la cultura coinvolta in primo luogo. Ora lascia che usi la cosa stupida". – Andrew

risposta

94

Non tutte le culture utilizzano lo stesso formato per le date e i valori decimali/valutari.

Questo importa per voi quando si sta convertendo in ingresso valori (leggi) che vengono memorizzati come stringhe a DateTime, float, double o decimal. Importerà anche se si tenta di formattare i suddetti tipi di dati sulle stringhe (scrittura) per la visualizzazione o l'archiviazione.

Se si conosce la specifica cultura in cui le date e i valori decimali/valutari saranno in anticipo, è possibile utilizzare quella specifica proprietà CultureInfo (ad esempio CultureInfo("en-GB")). Ad esempio se ti aspetti un input da parte dell'utente.

La proprietà CultureInfo.InvariantCulture viene utilizzata se si esegue la formattazione o l'analisi di una stringa che deve essere analizzabile da un pezzo di software indipendente dalle impostazioni locali dell'utente.

Il valore predefinito è CultureInfo.InstalledUICulture in modo che CultureInfo predefinito dipenda dalle impostazioni del sistema operativo in esecuzione. Questo è il motivo per cui dovresti sempre assicurarti che le informazioni sulla cultura si adattino alle tue intenzioni (vedi Martin's answer per una buona guida).

+3

"en-US", penso che in realtà dipenda dalle impostazioni del tuo sistema. – Tracker1

+35

Il valore predefinito non è 'en-US'. È la cultura locale. E 'InvariantCulture' viene utilizzato quando si desidera una formattazione neutra della cultura indipendente dal sistema locale. Ad esempio quando si lavora con formati di file basati su testo. – CodesInChaos

+14

Per aggiungere al commento @CodesInChaos: L'affermazione che _Il valore predefinito è CultureInfo ("en-US") _ è semplicemente sbagliato. Inoltre, la dichiarazione _La proprietà CultureInfo.InvariantCulture viene utilizzata quando non si è sicuri in anticipo di quale formato di cultura le date e i valori decimali/valutari saranno in._ è confuso. Usare l'attuale, l'invariante o una cultura specifica è qualcosa che dovrebbe essere una decisione consapevole, e se ti sbagli puoi alienare i tuoi utenti (non statunitensi). Non dovresti usare la cultura invariante se sei "insicuro". Devi essere sicuro prima del tempo. –

2

JetBrains offre un ragionevole explanation, ma se sto lavorando su un sito che so sarà solo in inglese, ho appena ignorato il suggerimento.

94

quando i numeri, le date e gli orari sono formattati in stringhe o analizzati da stringhe una cultura viene utilizzato per determinare come è fatto . Per esempio. nella dominante en-US cultura si hanno queste rappresentazioni di stringa:

  • 1.000.000.00 - un milione con una frazione a due cifre
  • 2013/01/29 - data della presente pubblicazione

Nella mia cultura (da-DK) i valori hanno questa rappresentazione di stringa:

  • 1.000.000 , 00 - un milione con una frazione a due cifre
  • 29-01-2013 - data della presente pubblicazione

Nel sistema operativo Windows l'utente può persino personalizzare come numeri e data/ora sono formattati e può anche scegliere un'altra cultura rispetto alla cultura del suo sistema operativo. La formattazione utilizzata è la scelta dell'utente che è come dovrebbe essere.

Quindi, quando si formatta un valore da visualizzare per l'utente che utilizza per esempio ToString o String.Format o analizzato da una stringa utilizzando DateTime.Parse o Decimal.Parse il default è quello di utilizzare il CultureInfo.CurrentCulture. Ciò consente all'utente di controllare la formattazione.

Tuttavia, un sacco di formattazione e analisi delle stringhe non sono in realtà stringhe scambiate tra l'applicazione e l'utente ma tra l'applicazione e alcuni formati di dati (ad esempio un file XML o CSV). In tal caso non si desidera utilizzare CultureInfo.CurrentCulture perché se la formattazione e l'analisi vengono eseguiti con culture diverse possono interrompersi. In tal caso, si desidera utilizzare CultureInfo.InvariantCulture (che si basa sulla coltura en-US). Ciò garantisce che i valori possano andare in giro senza problemi.

La ragione per cui ReSharper ti dà l'avvertimento è che alcuni scrittori di applicazione non sono a conoscenza di questa distinzione che può portare a risultati indesiderati, ma non hanno mai scoprire questo perché la loro CultureInfo.CurrentCulture è en-US che ha lo stesso comportamento come CultureInfo.InvariantCulture. Tuttavia, non appena l'applicazione viene utilizzata in un'altra cultura in cui esiste la possibilità di utilizzare una cultura per la formattazione e un'altra per l'analisi dell'applicazione potrebbe interrompersi.

Quindi, per riassumere:

  • Usa CultureInfo.CurrentCulture (l'impostazione predefinita), se si sta formattando o parsing di una stringa utente.
  • Utilizzare CultureInfo.InvariantCulture se si sta formattando o analizzando una stringa che deve essere analizzabile da un software.
  • Raramente utilizzare una cultura nazionale specifica perché l'utente non è in grado di controllare la formattazione e l'analisi.
+0

Per quanto riguarda l'ultimo punto, "Raramente utilizza una specifica cultura nazionale ...", la formattazione della valuta sarebbe un'eccezione? Per esempio, se ho una variabile 'Decimale' contenente un certo valore in dollari USA, vorrei fare un'eccezione e usare' en-US' come cultura quando la mostro per assicurarmi che non ottenga un risultato che sembra come un numero in euro? [Ho provato] (https://dotnetfiddle.net/WYpIvw) 'CultureInfo.InvariantCulture', ma ho preso questo per l'indicatore di valuta' ¤', quindi non sono sicuro che sia la strada giusta. –

+1

@JeffBridgman: Il mio consiglio è solo un consiglio generale e potrebbe non essere applicabile al caso specifico. Tuttavia, penserei che il modo in cui visualizzi il punto decimale (virgola o punto) dovrebbe essere qualcosa che l'utente controlla (ad esempio, usa CultureInfo.CurrentCulture'). Se oltre a visualizzare un numero è necessaria la valuta, forse dovresti farlo in modo coerente, ad esempio non utilizzando un 'CultureInfo' e invece usa il codice di valuta a tre lettere come" USD 1,234,56 ". Quindi non si entra nel problema di mappare una valuta in una cultura. –

17

Secondo Microsoft:

La proprietà CultureInfo.InvariantCulture non è né un neutrale né una cultura specifica . È un terzo tipo di cultura che è insensibile alla cultura. È associato alla lingua inglese ma non con un paese o una regione.

(da http://msdn.microsoft.com/en-us/library/4c5zdc6a(vs.71).aspx)

Così InvariantCulture è similair alla cultura "en-US", ma non esattamente la stessa cosa.Se si scrive:

var d = DateTime.Now; 
var s1 = d.ToString(CultureInfo.InvariantCulture); // "05/21/2014 22:09:28" 
var s2 = d.ToString(new CultureInfo("en-US"));  // "5/21/2014 10:09:28 PM" 

poi S1 e S2 avrà formato similair ma InvariantCulture aggiunge zeri e "en-US" utilizza AM o PM.

Così InvariantCulture è migliore per l'uso interno, quando ad esempio si salva una data in un file di testo o si analizzano i dati. E un CultureInfo specificato è migliore quando si presentano dati (data, valuta ...) all'utente finale.

4

Per cose come i numeri (punti decimali, virgole in quantità), di solito sono preferiti nella cultura specifica.

Un modo appropriato per fare questo sarebbe impostarlo a livello culturale (per il tedesco) come questo:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;