O que significa CultureInfo.InvariantCulture?

177

Eu tenho uma sequência de texto assim:

var foo = "FooBar";

Quero declarar uma segunda string chamada bare torná-la igual ao primeiro e quarto caracteres do meu primeiro foo, então faço assim:

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

Isso funciona como esperado, mas o ReSharper está me aconselhando a colocar Culture.InvariantCulturedentro dos meus colchetes, então essa linha acaba assim:

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

O que isso significa e afetará a execução do meu programa?

JMK
fonte
2
Veja esta pergunta do SO: stackoverflow.com/questions/8492449/…
msigman 18/03/2012
38
Para quem procura a resposta de 5 segundos: CultureInfo.InvariantCulture significa "Eu não ligo, não quero cultura envolvida em primeiro lugar. Agora, deixe-me usar a coisa idiota".
Andrew
5
@ Andrew Você pode reescrever todos os documentos da MS, pls?
Yatrix
3
@ Yatrix Sim, com certeza. Eu adoraria! Quem está pagando?
Andrew

Respostas:

154

Nem todas as culturas usam o mesmo formato para datas e valores decimais / moeda.

Isso importa para você quando você está convertendo os valores de entrada (ler) que são armazenados como cordas para DateTime, float, doubleou decimal. Também será importante se você tentar formatar os tipos de dados mencionados acima em seqüências de caracteres (gravação) para exibição ou armazenamento.

Se você souber em qual cultura específica suas datas e valores decimais / moeda serão antecipados, poderá usar essa CultureInfopropriedade específica (por exemplo CultureInfo("en-GB")). Por exemplo, se você espera uma entrada do usuário.

A CultureInfo.InvariantCulturepropriedade é usada se você estiver formatando ou analisando uma sequência que deve ser analisada por um software independente das configurações locais do usuário.

O valor padrão é CultureInfo.InstalledUICultureque o CultureInfo padrão depende das configurações do sistema operacional em execução. É por isso que você deve sempre garantir que as informações da cultura sejam adequadas à sua intenção (consulte a resposta de Martin para obter uma boa orientação).

JohnB
fonte
3
"en-US", acho que pode realmente depender das configurações do sistema.
Tracker1
44
O valor padrão não é en-US. É a cultura local. E InvariantCultureé usado quando você deseja formatação neutra para a cultura, independente do sistema local. Por exemplo, ao trabalhar com formatos de arquivo baseados em texto.
código é o seguinte
23
Para adicionar ao comentário @CodesInChaos: A afirmação de que o valor padrão é CultureInfo ("en-US") está simplesmente errada. Além disso, a declaração A propriedade CultureInfo.InvariantCulture é usada quando você não tem certeza antecipadamente do formato da cultura em que serão as datas e os valores decimais / moeda. É confuso. O uso da cultura atual, invariável ou específica é algo que deve ser uma decisão consciente e, se você errar, pode alienar seus usuários (fora dos EUA). Você não deve usar a cultura invariável se não tiver certeza. Você precisa ter certeza de antecedência.
Martin Liversage 7/03/13
3
-1 devido aos problemas mencionados em outros comentários. A resposta de Martin é mais útil porque indica quando usar e não usar cada cultura.
Ed Greaves
"se você trabalha exclusivamente em inglês americano, não precisa se preocupar com isso.": Incorreto, você pode trabalhar exclusivamente em inglês americano, mas o software pode ser executado em um "en-GB" ou um "de -DE ", então fará a diferença, além de poder levar a cultura do cliente (se você o disser no arquivo web.config), e isso também não pode ser" en-US "...
Stefan Steiger
151

Quando números, datas e horas são formatados em cadeias ou analisados ​​a partir de cadeias, uma cultura é usada para determinar como isso é feito. Por exemplo, na en-UScultura dominante , você tem estas representações de string:

  • 1.000.000,00 - um milhão com uma fração de dois dígitos
  • 29/1/2013 - data desta postagem

Na minha cultura ( da-DK), os valores têm esta representação em cadeia:

  • 1.000.000,00 - um milhão com uma fração de dois dígitos
  • 29-01-2013 - data desta postagem

No sistema operacional Windows, o usuário pode até personalizar como os números e a data / hora são formatados e também pode escolher outra cultura além da cultura do sistema operacional. A formatação utilizada é a escolha do usuário, como deve ser.

Portanto, quando você formata um valor a ser exibido ao usuário usando, por exemplo, ToStringou String.Formatou analisado uma string usando DateTime.Parseou Decimal.Parseo padrão é usar o CultureInfo.CurrentCulture. Isso permite que o usuário controle a formatação.

No entanto, muitas formatações e análises de strings não são trocadas entre o aplicativo e o usuário, mas entre o aplicativo e alguns formatos de dados (por exemplo, um arquivo XML ou CSV). Nesse caso, você não deseja usá-lo CultureInfo.CurrentCultureporque, se a formatação e a análise forem feitas com diferentes culturas, elas poderão quebrar. Nesse caso, você deseja usar CultureInfo.InvariantCulture(que é baseado na en-UScultura). Isso garante que os valores possam percorrer sem problemas.

O motivo pelo qual o ReSharper avisa é que alguns criadores de aplicativos desconhecem essa distinção, o que pode levar a resultados indesejados, mas eles nunca descobrem isso porque CultureInfo.CurrentCulturesão eles en-USque têm o mesmo comportamento CultureInfo.InvariantCulture. No entanto, assim que o aplicativo é usado em outra cultura, existe a chance de usar uma cultura para formatação e outra para analisar o aplicativo.

Então, para resumir:

  • Use CultureInfo.CurrentCulture(o padrão) se você estiver formatando ou analisando uma sequência de caracteres do usuário.
  • Use CultureInfo.InvariantCulturese você estiver formatando ou analisando uma sequência que deve ser analisada por um software.
  • Raramente use uma cultura nacional específica porque o usuário não consegue controlar como a formatação e a análise são feitas.
Martin Liversage
fonte
1
Em relação ao último ponto, "Raramente use uma cultura nacional específica ...", a formatação de moeda seria uma exceção? Por exemplo, se eu tiver uma Decimalvariável que contenha um determinado valor em dólares americanos, gostaria de fazer uma exceção e usar en-UScomo cultura ao exibi-la para garantir que não obtenho um resultado que se pareça com um número em euros? Eu tentei CultureInfo.InvariantCulture , mas consegui isso para o marcador de moeda ¤, então não tenho certeza de que é o caminho certo.
11137 Jeff B
1
@JeffBridgman: Meu conselho é apenas um conselho geral e pode não se aplicar ao seu caso específico. No entanto, eu acho que a maneira como você exibe o ponto decimal (vírgula ou ponto) deve ser algo que o usuário controla (por exemplo, uso CultureInfo.CurrentCulture). Se você, além de exibir um número, precisar da moeda, talvez faça isso de maneira consistente, ou seja, sem usar um CultureInfoe, em vez disso, use o código de moeda de três letras como USD 1,234.56. Então você não entra em problemas de mapear uma moeda para uma cultura.
Martin Liversage
26

De acordo com a Microsoft:

A propriedade CultureInfo.InvariantCulture não é uma cultura neutra nem específica. É um terceiro tipo de cultura que é insensível à cultura. Está associado ao idioma inglês, mas não a um país ou região.

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

Portanto, a InvariantCulture é semelhante à cultura "en-US", mas não é exatamente a mesma. Se você escrever:

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"

então s1 e s2 terão formato semelhante, mas InvariantCulture adiciona zeros à esquerda e "en-US" usa AM ou PM.

Portanto, InvariantCulture é melhor para uso interno, quando você salva uma data em um arquivo de texto ou analisa dados. E um CultureInfo especificado é melhor quando você apresenta dados (data, moeda ...) para o usuário final.

happybits
fonte
3
Executei seu código de exemplo para confirmar: InvariantCulture usa American MM / dd / aaaa em vez de seguir o formato ISO 8601 no primeiro ano. Apesar disso, destina-se ao armazenamento portátil e processamento mecânico, e não ao consumo humano. Como confundindo
Max Barraclough
4

Para coisas como números (casas decimais, vírgulas em quantidades), elas geralmente são preferidas na cultura específica.

Uma maneira apropriada de fazer isso seria configurá-lo no nível da cultura (para alemão) assim:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;
Máquina de Turing
fonte
4

O JetBrains oferece uma explicação razoável ,

"A conversão ad-hoc de estruturas de dados em texto depende muito da cultura atual e pode levar a resultados indesejados quando o código é executado em uma máquina cuja localidade difere da do desenvolvedor original. Para evitar ambiguidades, o ReSharper avisa sobre: quaisquer instâncias no código em que esse problema possa ocorrer ".

mas se estou trabalhando em um site que sei que será apenas em inglês, simplesmente ignoro a sugestão.

Neil Thompson
fonte