Que signifie CultureInfo.InvariantCulture?

178

J'ai une chaîne de texte comme ceci:

var foo = "FooBar";

Je veux déclarer une deuxième chaîne appelée baret la rendre égale au premier et au quatrième caractère de mon premier foo, donc je fais ceci comme ceci:

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

Cela fonctionne comme prévu, mais ReSharper me conseille de mettre Culture.InvariantCultureentre mes crochets, donc cette ligne se termine comme suit:

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

Qu'est-ce que cela signifie et affectera-t-il le fonctionnement de mon programme?

JMK
la source
2
Voir cette question SO: stackoverflow.com/questions/8492449/…
msigman
39
Pour ceux qui recherchent la réponse en 5 secondes: CultureInfo.InvariantCulture signifie "Je m'en fous, je ne veux pas que la culture soit impliquée en premier lieu. Maintenant, laissez-moi utiliser la chose stupide."
Andrew
5
@Andrew Pouvez-vous réécrire tous les documents de MS, pls?
Yatrix le
3
@Yatrix Ouais, c'est sûr. J'adorerais! Qui paie?
Andrew le

Réponses:

155

Toutes les cultures n'utilisent pas le même format pour les dates et les valeurs décimales / monétaires.

Ce sera important pour vous lorsque vous êtes en train de convertir des valeurs d'entrée (de lecture) qui sont stockés sous forme de chaînes à DateTime, float, doubleou decimal. Cela importera également si vous essayez de formater les types de données susmentionnés en chaînes (écriture) pour l'affichage ou le stockage.

Si vous savez à l'avance dans quelle culture spécifique vos dates et vos valeurs décimales / monétaires se trouveront, vous pouvez utiliser cette CultureInfopropriété spécifique (c'est-à-dire CultureInfo("en-GB")). Par exemple, si vous attendez une entrée utilisateur.

La CultureInfo.InvariantCulturepropriété est utilisée si vous formatez ou analysez une chaîne qui doit être analysable par un logiciel indépendant des paramètres locaux de l'utilisateur.

La valeur par défaut est CultureInfo.InstalledUICulturedonc le CultureInfo par défaut dépend des paramètres du système d'exploitation en cours d'exécution. C'est pourquoi vous devez toujours vous assurer que les informations sur la culture correspondent à votre intention (voir la réponse de Martin pour une bonne ligne directrice).

JohnB
la source
3
"en-US" cependant, je pense que cela peut dépendre de vos paramètres système.
Tracker1
44
La valeur par défaut ne l'est pas en-US. C'est la culture locale. Et InvariantCultureest utilisé lorsque vous souhaitez une mise en forme neutre de la culture, indépendante du système local. Par exemple, lorsque vous travaillez avec des formats de fichiers basés sur du texte.
CodesInChaos
23
Pour ajouter au commentaire @CodesInChaos: L'affirmation selon laquelle la valeur par défaut est CultureInfo ("en-US") est tout simplement fausse. En outre, l'instruction La propriété CultureInfo.InvariantCulture est utilisée lorsque vous n'êtes pas sûr à l'avance du format de culture dans lequel vos dates et vos valeurs décimales / monétaires seront. Est déroutante. Utiliser soit le courant, l'invariant ou une culture spécifique est quelque chose qui devrait être une décision consciente, et si vous vous trompez, vous pouvez aliéner vos utilisateurs (non américains). Vous ne devriez pas utiliser la culture invariante si vous n'êtes pas sûr. Vous devez être sûr à l'avance.
Martin Liversage
3
-1 en raison des problèmes mentionnés dans d'autres commentaires. La réponse de Martin est plus utile car elle vous indique quand utiliser et ne pas utiliser chaque culture.
Ed Greaves
"si vous travaillez exclusivement en anglais américain, vous n'avez pas à vous en préoccuper.": Incorrect, vous travaillez peut-être exclusivement en anglais américain, mais le logiciel peut fonctionner sur un "en-GB" ou un "de -DE ", alors cela fera une différence, en plus cela peut prendre la culture du client (si vous le dites dans le fichier web.config), et cela pourrait ne pas être" en-US "non plus ...
Stefan Steiger
152

Lorsque les nombres, les dates et les heures sont formatés en chaînes ou analysés à partir de chaînes, une culture est utilisée pour déterminer comment cela est fait. Par exemple, dans la en-USculture dominante , vous avez ces représentations sous forme de chaîne:

  • 1,000,000.00 - un million avec une fraction à deux chiffres
  • 29/1/2013 - date de l'affichage

Dans ma culture ( da-DK), les valeurs ont cette représentation sous forme de chaîne:

  • 1.000.000,00 - un million avec une fraction à deux chiffres
  • 29-01-2013 - date de cet affichage

Dans le système d'exploitation Windows, l'utilisateur peut même personnaliser le formatage des nombres et des dates / heures et peut également choisir une autre culture que la culture de son système d'exploitation. La mise en forme utilisée est le choix de l'utilisateur qui doit être ainsi.

Ainsi, lorsque vous formatez une valeur à afficher pour l'utilisateur en utilisant par exemple ToStringou String.Formatou analysée à partir d'une chaîne en utilisant DateTime.Parseou, Decimal.Parsela valeur par défaut est d'utiliser leCultureInfo.CurrentCulture . Cela permet à l'utilisateur de contrôler le formatage.

Cependant, une grande partie du formatage et de l'analyse des chaînes ne sont en fait pas des chaînes échangées entre l'application et l'utilisateur mais entre l'application et certains formats de données (par exemple un fichier XML ou CSV). Dans ce cas, vous ne souhaitez pas utiliser, CultureInfo.CurrentCulturecar si le formatage et l'analyse sont effectués avec des cultures différentes, ils peuvent être interrompus. Dans ce cas, vous souhaitez utiliser CultureInfo.InvariantCulture(qui est basé sur la en-USculture). Cela garantit que les valeurs peuvent aller-retour sans problème.

La raison pour laquelle ReSharper vous avertit est que certains auteurs d'applications ne sont pas conscients de cette distinction qui peut conduire à des résultats inattendus, mais ils ne le découvrent jamais car leur CultureInfo.CurrentCultureest en-USqui a le même comportement queCultureInfo.InvariantCulture . Cependant, dès que l'application est utilisée dans une autre culture où il est possible d'utiliser une culture pour la mise en forme et une autre pour l'analyse, l'application peut être interrompue.

Donc pour résumer:

  • Utilisation CultureInfo.CurrentCulture (valeur par défaut) si vous formatez ou analysez une chaîne utilisateur.
  • Utilisation CultureInfo.InvariantCulture si vous formatez ou analysez une chaîne qui doit être analysable par un logiciel.
  • Utilisez rarement une culture nationale spécifique car l'utilisateur est incapable de contrôler la façon dont le formatage et l'analyse sont effectués.
Martin Liversage
la source
1
En ce qui concerne le dernier point, "Utiliser rarement une culture nationale spécifique ...", le formatage des devises serait-il une exception? Par exemple, si j'ai une Decimalvariable contenant une certaine valeur en dollars américains, est-ce que je voudrais faire une exception et l'utiliser en-UScomme culture lors de son affichage pour m'assurer de ne pas obtenir un résultat qui ressemble à un nombre en euros? J'ai essayé CultureInfo.InvariantCulture , mais j'ai obtenu ceci pour le marqueur de devise ¤, donc je ne suis pas sûr que ce soit la bonne façon.
Jeff B du
1
@JeffBridgman: Mon conseil n'est qu'un conseil général et peut ne pas s'appliquer à votre cas particulier. Cependant, je pense que la façon dont vous affichez le point décimal (virgule ou point) devrait être quelque chose que l'utilisateur contrôle (par exemple, utilise CultureInfo.CurrentCulture). Si, en plus d'afficher un nombre, vous avez besoin de la devise, vous devriez peut-être le faire de manière cohérente, c'est-à-dire ne pas utiliser de CultureInfoet utiliser à la place le code de devise à trois lettres comme USD 1,234.56. Ensuite, vous n'entrez pas dans les problèmes de mappage d'une monnaie à une culture.
Martin Liversage
26

Selon Microsoft:

La propriété CultureInfo.InvariantCulture n'est ni une culture neutre ni une culture spécifique. C'est un troisième type de culture qui est insensible à la culture. Il est associé à la langue anglaise mais pas à un pays ou une région.

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

Donc InvariantCulture est similaire à la culture "en-US" mais pas exactement la même chose. Si vous écrivez:

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"

alors s1 et s2 auront un format similaire mais InvariantCulture ajoute des zéros non significatifs et "en-US" utilise AM ou PM.

Donc InvariantCulture est meilleur pour un usage interne, lorsque vous enregistrez par exemple une date dans un fichier texte ou analysez des données. Et un CultureInfo spécifié est meilleur lorsque vous présentez des données (date, devise ...) à l'utilisateur final.

happybits
la source
3
J'ai couru votre exemple de code pour confirmer: InvariantCulture utilise American MM / dd / yyyy plutôt que de suivre le format ISO 8601 Year-Go-First. Malgré cela, il est destiné au stockage portable et au traitement mécanique, plutôt qu'à la consommation humaine. How confusing
Max Barraclough
4

Pour des choses comme les nombres (points décimaux, virgules dans les montants), ils sont généralement préférés dans la culture spécifique.

Une manière appropriée de le faire serait de le définir au niveau de la culture (pour l'allemand) comme ceci:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;
Machine de Turing
la source
4

JetBrains offre une explication raisonnable ,

"La conversion ad hoc de structures de données en texte dépend en grande partie de la culture actuelle et peut conduire à des résultats inattendus lorsque le code est exécuté sur une machine dont les paramètres régionaux diffèrent de ceux du développeur d'origine. Pour éviter les ambiguïtés, ReSharper vous avertit de toutes les instances dans le code où un tel problème peut se produire. "

mais si je travaille sur un site dont je sais qu'il sera en anglais uniquement, j'ignore simplement la suggestion.

Neil Thompson
la source