Cosa significa CultureInfo.InvariantCulture?


178

Ho una stringa di testo in questo modo:

var foo = "FooBar";

Voglio dichiarare una seconda stringa chiamata bare renderla uguale al primo e al quarto carattere del mio primo foo, quindi lo faccio in questo modo:

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

Funziona come previsto, ma ReSharper mi sta suggerendo di mettere Culture.InvariantCulturetra le mie parentesi, quindi questa linea finisce così:

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

Cosa significa questo e influenzerà il modo in cui il mio programma viene eseguito?


2
Vedere questa domanda SO: stackoverflow.com/questions/8492449/...
msigman

39
Per chi cerca la risposta di 5 secondi: CultureInfo.InvariantCulture significa "Non mi interessa, non voglio che la cultura sia coinvolta in primo luogo. Ora lasciami usare la cosa stupida".
Andrew,

5
@Andrew Puoi riscrivere tutti i documenti di MS, pls?
Yatrix,

3
@Yatrix Sì, certo. Mi piacerebbe! Chi paga?
Andrew

Risposte:


155

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

Questo avrà importanza per voi quando si sta convertendo i valori di ingresso (lettura) che vengono memorizzati come stringhe a DateTime, float, doubleo decimal. Importerà anche se si tenta di formattare i tipi di dati di cui sopra in stringhe (scrittura) per la visualizzazione o l'archiviazione.

Se sai quale cultura specifica in cui le tue date e i valori decimali / valutari saranno in anticipo, puoi usare quella CultureInfoproprietà specifica (es CultureInfo("en-GB").). Ad esempio, se ti aspetti un input da parte dell'utente.

La CultureInfo.InvariantCultureproprietà viene utilizzata se si sta formattando o analizzando una stringa che deve essere analizzabile da un software indipendentemente dalle impostazioni locali dell'utente.

Il valore predefinito è CultureInfo.InstalledUICulturequindi CultureInfo predefinito dipende 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 la risposta di Martin per una buona guida).


3
"en-US", tuttavia, penso che potrebbe effettivamente dipendere dalle impostazioni del sistema.
Tracker 1

44
Il valore predefinito non lo è en-US. È la cultura locale. E InvariantCultureviene utilizzato quando si desidera una formattazione neutra per la cultura indipendente dal sistema locale. Ad esempio quando si lavora con formati di file basati su testo.
CodesInChaos

23
Per aggiungere al commento @CodesInChaos: l'affermazione che il valore predefinito è CultureInfo ("en-US") è semplicemente errata. Inoltre, l'istruzione La proprietà CultureInfo.InvariantCulture viene utilizzata quando non si è sicuri in anticipo in quale formato di cultura saranno presenti le date e i valori decimali / valutari . L'uso della cultura attuale, invariante o specifica è qualcosa che dovrebbe essere una decisione consapevole e, se sbagli, puoi alienare i tuoi utenti (non statunitensi). Non dovresti usare la cultura invariante se non sei "sicuro". Devi essere sicuro in anticipo.
Martin Liversage

3
-1 a causa dei problemi menzionati in altri commenti. La risposta di Martin è più utile perché ti dice quando usare e non usare ogni cultura.
Ed Greaves,

"se lavori esclusivamente in inglese americano, non devi preoccuparti di questo.": In caso contrario, potresti lavorare esclusivamente in inglese americano, ma il software potrebbe essere eseguito su un "en-GB" o un "de -DE ", allora farà la differenza, inoltre può richiedere la cultura del client (se lo dici nel file web.config), e potrebbe non essere nemmeno" en-US "...
Stefan Steiger

152

Quando numeri, date e ore vengono formattati in stringhe o analizzati da stringhe, viene utilizzata una cultura per determinare come viene eseguita. Ad esempio nella en-UScultura dominante hai queste rappresentazioni di stringhe:

  • 1.000.000,00 - un milione con una frazione di due cifre
  • 29/01/2013 - data di pubblicazione

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

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

Nel sistema operativo Windows, l'utente può persino personalizzare il modo in cui i numeri e la 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.

Pertanto, quando si formatta un valore da visualizzare all'utente utilizzando ad esempio ToStringo String.Formatoppure analizzato da una stringa utilizzando DateTime.Parseo Decimal.Parsel'impostazione predefinita è utilizzare il CultureInfo.CurrentCulture. Ciò consente all'utente di controllare la formattazione.

Tuttavia, molta 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 quel caso non vuoi usarlo CultureInfo.CurrentCultureperché se la formattazione e l'analisi vengono eseguite con culture diverse può rompersi. In tal caso, si desidera utilizzare CultureInfo.InvariantCulture(basato sulla en-UScultura). Ciò garantisce che i valori possano essere di andata e ritorno senza problemi.

La ragione per cui ReSharper ti dà l'avvertimento è che alcuni autori di applicazioni non sono consapevoli di questa distinzione che può portare a risultati non voluti, ma non lo scoprono mai perché il loro CultureInfo.CurrentCultureè en-USche ha lo stesso comportamento di 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:

  • Utilizzare CultureInfo.CurrentCulture(impostazione predefinita) se si sta formattando o analizzando una stringa utente.
  • Utilizzare CultureInfo.InvariantCulturese si sta formattando o analizzando una stringa che dovrebbe essere analizzabile da un software.
  • Usa raramente una cultura nazionale specifica perché l'utente non è in grado di controllare la formattazione e l'analisi.

1
Per quanto riguarda l'ultimo punto, "Usa raramente una cultura nazionale specifica ...", la formattazione della valuta sarebbe un'eccezione? Ad esempio, se ho una Decimalvariabile che contiene un determinato valore in dollari statunitensi, vorrei fare un'eccezione e usarla en-UScome cultura quando la visualizzo per assicurarmi di non ottenere un risultato simile a un numero in euro? Ho provato CultureInfo.InvariantCulture , ma ho ottenuto questo per l'indicatore di valuta ¤, quindi non sono sicuro che sia la strada giusta.
Jeff B,

1
@JeffBridgman: il mio consiglio è solo un consiglio generale e potrebbe non essere applicabile al tuo caso specifico. Tuttavia, penso che il modo in cui visualizzi il punto decimale (virgola o punto) dovrebbe essere qualcosa che l'utente controlla (es. Usare CultureInfo.CurrentCulture). Se oltre a visualizzare un numero hai bisogno della valuta, forse dovresti farlo in modo coerente, cioè non usare un CultureInfoe invece usare il codice valuta a tre lettere come USD 1,234.56. Quindi non ti imbatti nei problemi di mappare una valuta su una cultura.
Martin Liversage,

26

Secondo Microsoft:

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

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

Quindi InvariantCulture è simile alla cultura "en-US" ma non è esattamente la stessa. Se scrivi:

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"

quindi s1 e s2 avranno un formato simile ma InvariantCulture aggiunge zero iniziali e "en-US" usa AM o PM.

Quindi InvariantCulture è migliore per l'uso interno, ad esempio quando 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.


3
Ho eseguito il tuo codice di esempio per confermare: InvariantCulture utilizza MM / gg / aaaa americani anziché seguire il formato ISO 8601 per il primo anno. Nonostante ciò è destinato allo stoccaggio portatile e all'elaborazione meccanica, piuttosto che al consumo umano. Che confusione
Max Barraclough il

4

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

Un modo appropriato per farlo sarebbe impostarlo a livello di cultura (per il tedesco) in questo modo:

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

4

JetBrains offre una spiegazione ragionevole ,

"La conversione ad hoc delle strutture di dati in testo dipende in gran parte dalla cultura corrente e può portare a risultati non intenzionali quando il codice viene eseguito su una macchina le cui impostazioni locali differiscono da quelle dello sviluppatore originale. Per prevenire ambiguità, ReSharper ti avverte di qualsiasi istanza nel codice in cui si può verificare un simile problema. "

ma se sto lavorando su un sito che so sarà solo in inglese, ignoro solo il suggerimento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.