Что означает CultureInfo.InvariantCulture?

178

У меня есть строка текста, например, так:

var foo = "FooBar";

Я хочу объявить вторую строку с именем barи сделать ее равной первому и четвертому символу моего первого foo, поэтому я делаю это так:

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

Это работает, как и ожидалось, но ReSharper советует мне заключить Culture.InvariantCultureв скобки, так что эта строка заканчивается так:

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

Что это значит и повлияет ли это на работу моей программы?

JMK
источник
2
Посмотрите этот ТАК вопрос: stackoverflow.com/questions/8492449/…
msigman
39
Для тех, кто ищет 5-секундный ответ: CultureInfo.InvariantCulture означает «Мне все равно, я не хочу, чтобы культура была вовлечена в первую очередь. Теперь позвольте мне использовать эту глупость».
Андрей
5
@ Andrew Можете ли вы переписать все документы MS, пожалуйста?
Ятрикс
3
@Yatrix Да, конечно. С удовольствием! Кто платит?
Андрей

Ответы:

155

Не все культуры используют один и тот же формат для дат и десятичных значений / значений валют.

Это важно для вас , когда вы преобразования входных значений (чтение) , которые хранятся в виде строки в DateTime, float, doubleили decimal. Также будет иметь значение, если вы попытаетесь отформатировать вышеупомянутые типы данных в строки (запись) для отображения или хранения.

Если вы знаете, в какой конкретной культуре будут ваши даты и десятичные значения / значения валют, вы можете использовать это конкретное CultureInfoсвойство (то есть CultureInfo("en-GB")). Например, если вы ожидаете ввода пользователя.

Это CultureInfo.InvariantCultureсвойство используется, если вы форматируете или анализируете строку, которая должна анализироваться программным обеспечением независимо от локальных настроек пользователя.

По умолчанию используется значение CultureInfo.InstalledUICultureCultureInfo, которое зависит от настроек операционной системы. Вот почему вы всегда должны следить за тем, чтобы информация о культуре соответствовала вашим намерениям (см . Ответ Мартина для хорошего руководства).

Johnb
источник
3
«en-US», хотя, я думаю, это может зависеть от настроек вашей системы.
Tracker1
44
Значением по умолчанию не является en-US. Это местная культура. И InvariantCultureиспользуется, когда вы хотите форматирование, не зависящее от культуры, которое не зависит от локальной системы. Например, при работе с текстовыми форматами файлов.
CodesInChaos
23
Чтобы добавить комментарий @CodesInChaos: Утверждение, что значением по умолчанию является CultureInfo ("en-US") , просто неверно. Кроме того, выражение Свойство CultureInfo.InvariantCulture используется, когда вы заранее не уверены, в каком культурном формате будут ваши даты и десятичные значения / значения валют . Использование текущей, инвариантной или конкретной культуры - это то, что должно быть осознанным решением, и если вы ошибетесь, вы можете оттолкнуть своих (не американских) пользователей. Вы не должны использовать инвариантную культуру, если вы «не уверены». Вы должны быть уверены заранее.
Мартин Ливерсэйдж
3
-1 из-за проблем, упомянутых в других комментариях. Ответ Мартина более полезен, потому что он говорит вам, когда использовать, а не использовать каждую культуру.
Эд Гривз
«Если вы работаете исключительно на американском английском, вам не нужно об этом беспокоиться». Неправильно, вы можете работать исключительно на американском английском, но программное обеспечение может работать на «en-GB» или «de». -DE "сервер, тогда это будет иметь значение, плюс он может принять культуру клиента (если вы так говорите в файле web.config), и это также не может быть" en-US "...
Стефан Штайгер
152

Когда числа, даты и время форматируются в строки или анализируются из строк, для определения того, как это делается, используется культура. Например, в доминирующей en-USкультуре у вас есть эти строковые представления:

  • 1 000 000,00 - один миллион с двузначной дробью
  • 29.01.2013 - дата публикации

В моей культуре ( da-DK) значения имеют строковое представление:

  • 1.000.000,00 - миллион с двузначной дробью
  • 29-01-2013 - дата этой публикации

В операционной системе Windows пользователь может даже настроить форматирование чисел и даты / времени, а также выбрать другую культуру, отличную от культуры его операционной системы. Используемое форматирование - выбор пользователя, каким он должен быть.

Таким образом , при форматировании значения , которое будет отображаться пользователю , используя, например , ToStringили String.Formatили разобрано из строки , используя DateTime.Parseили Decimal.Parseпо умолчанию использовать CultureInfo.CurrentCulture. Это позволяет пользователю контролировать форматирование.

Тем не менее, большая часть форматирования и синтаксического анализа строк - это на самом деле не строки, которыми обмениваются приложение и пользователь, а между приложением и некоторым форматом данных (например, файлом XML или CSV). В этом случае вы не хотите использовать, CultureInfo.CurrentCultureпотому что, если форматирование и синтаксический анализ выполняются с разными культурами, он может сломаться. В этом случае вы хотите использовать CultureInfo.InvariantCulture(который основан на en-USкультуре). Это гарантирует, что значения могут идти в обе стороны без проблем.

Причина , по которой ReSharper дает предупреждение, что некоторые авторы приложения не знает об этом различии , которое может привести к нежелательным результатам , но они никогда не обнаружить это , потому что их CultureInfo.CurrentCultureIS , en-USкоторый имеет такое же поведение , как CultureInfo.InvariantCulture. Тем не менее, как только приложение используется в другой культуре, где существует вероятность использования одной культуры для форматирования, а другой для анализа приложения, может произойти сбой.

Итак, подведем итог:

  • Используйте CultureInfo.CurrentCulture(по умолчанию), если вы форматируете или анализируете строку пользователя.
  • Используйте, CultureInfo.InvariantCultureесли вы форматируете или анализируете строку, которая должна быть проанализирована программным обеспечением.
  • Редко используйте определенную национальную культуру, потому что пользователь не может контролировать, как выполняется форматирование и анализ.
Мартин Ливерсаж
источник
1
Что касается последнего пункта, «Редко использовать определенную национальную культуру ...», будет ли форматирование валюты исключением? Например, если у меня есть Decimalпеременная, содержащая определенное значение в долларах США, хочу ли я сделать исключение и использовать его en-USпри отображении, чтобы убедиться, что я не получаю результат, похожий на число в евро? Я пытался CultureInfo.InvariantCulture , но получил это для маркера валюты ¤, так что я не уверен, что это правильный путь.
Джефф Б
1
@JeffBridgman: Мой совет - просто общий совет и может не относиться к вашему конкретному случаю. Однако я думаю, что способ отображения десятичной точки (запятая или точка) должен быть тем, что пользователь контролирует (например, использует CultureInfo.CurrentCulture). Если вам, помимо отображения числа, нужна валюта, то, возможно, вам следует делать это согласованным образом, то есть не использовать a, CultureInfoа вместо этого использовать трехбуквенный код валюты, например USD 1,234.56. Тогда вы не будете сталкиваться с проблемами сопоставления валюты с культурой.
Мартин Ливерсэйдж
26

По словам Microsoft:

Свойство CultureInfo.InvariantCulture не является ни нейтральной, ни конкретной культурой. Это третий тип культуры, который нечувствителен к культуре. Это связано с английским языком, но не со страной или регионом.

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

Таким образом, InvariantCulture похож на культуру "en-US", но не совсем то же самое. Если вы напишите:

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"

тогда s1 и s2 будут иметь формат similair, но InvariantCulture добавляет ведущие нули, а «en-US» использует AM или PM.

Таким образом, InvariantCulture лучше использовать для внутреннего использования, когда вы, например, сохраняете дату в текстовый файл или анализируете данные. И указанное CultureInfo лучше, когда вы предоставляете данные (дата, валюта ...) конечному пользователю.

happybits
источник
3
Я запустил ваш пример кода для подтверждения: InvariantCulture использует американский MM / dd / yyyy вместо того, чтобы следовать стандарту ISO 8601 «год за годом». Несмотря на это он предназначен для портативного хранения и механической обработки, а не для потребления человеком. Как запутанно
Макс Барракло
4

Для таких вещей, как числа (десятичные точки, запятые в количествах), они обычно предпочитаются в конкретной культуре.

Подходящий способ сделать это можно установить на уровне культуры (для немецкого языка) следующим образом:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;
Машина Тьюринга
источник
4

JetBrains предлагает разумное объяснение ,

«Специальное преобразование структур данных в текст в значительной степени зависит от текущей культуры и может привести к непредвиденным результатам, когда код выполняется на машине, язык которой отличается от языка исходного разработчика. Чтобы предотвратить неоднозначности, ReSharper предупреждает вас о любые случаи в коде, где может возникнуть такая проблема. "

но если я работаю над сайтом, который, как я знаю, будет только на английском, я просто проигнорирую это предложение.

Нил Томпсон
источник