Почему разделитель групп номера культуры .NET de-CH отличается локально и в Azure?
Я вижу другой символ Юникода в качестве разделителя группы номеров для культуры "de-CH" при работе на локальном рабочем столе и в Azure.
Когда следующий код запускается на моем рабочем столе в .NET Core 3.1 или .NET Framework 4.7.2, он выводит 2019
что-то похожее на апостроф, но не то же самое.
При запуске в Azure, например в https://try.dot.netили (слегка измененный) в функции Azure, работающей в .NET Core 3.1 (в службе приложений на базе Windows), это приводит 0027
к стандартному апострофу ASCII.
using System;
using System.Linq;
using System.Globalization;
Console.WriteLine(((int)(CultureInfo
.GetCultureInfo("de-CH")
.NumberFormat
.NumberGroupSeparator
.Single())) // Just getting the single character as an int
.ToString("X4") // unicode value of that character
);
Результатом этого является то, что попытка синтаксического анализа строки 4'200.000
(где апостроф - Unicode 0027
) на локальном рабочем столе с использованием языка и региональных параметров de-CH завершается неудачно, но работает в Azure.
Почему разница?
Ответы
В этом блоге Microsoft, написанном Шоном Стилом, объясняется, почему вы не должны полагаться на стабильность конкретной культуры (полностью цитируется, поскольку ее больше нет в сети на MSDN):
https://web.archive.org/web/20190110065542/https://blogs.msdn.microsoft.com/shawnste/2005/04/05/culture-data-shouldnt-be-considered-stable-except-for-invariant/
Данные CultureInfo и RegionInfo представляют культурные, региональные, административные или пользовательские предпочтения в отношении культурных параметров. Приложения НЕ должны делать никаких предположений, полагаясь на стабильность этих данных. Единственное исключение (это правило, поэтому, конечно, есть исключение) - для CultureInfo.InvariantCulture. CultureInfo.InvariantCulture должен оставаться стабильным даже между версиями.
Есть много причин, по которым культурные данные могут измениться. С Whidbey и Custom Cultures список становится немного длиннее.
- Наиболее очевидная причина в том, что в данных есть ошибка, и нам пришлось внести изменения. (Хотите верьте, хотите нет, мы делаем ошибки ;-)) В этом случае нашим пользователям (и вам тоже) нужны культурно корректные данные, поэтому мы должны исправить ошибку, даже если она нарушает работу существующих приложений.
- Другая причина в том, что культурные предпочтения могут измениться. Это может произойти разными способами, но это действительно так:
- Глобальная осведомленность, межкультурный обмен, меняющаяся роль компьютеров и т. Д. - все это может влиять на культурные предпочтения.
- Международные договоры, торговля и т. Д. Могут изменять ценности. Принятие евро изменило символ валюты многих стран на евро.
- Национальные или региональные правила также могут повлиять на эти значения.
- Предпочтительное написание слов может со временем измениться.
- Предпочтительные форматы даты и т. Д. Могут измениться.
- Для культуры может существовать множество предпочтений. Предпочтительный лучший выбор может со временем измениться.
- Пользователи могли переопределить некоторые значения, например форматы даты или времени. Их можно запросить без переопределения пользователя, однако мы рекомендуем приложениям рассмотреть возможность использования переопределения пользователя.
- Пользователи или администраторы могли создать заменяющую культуру, заменив общие значения по умолчанию для культуры специфическими для компании, региональными или другими вариантами стандартных данных.
- В некоторых культурах могут быть предпочтения, которые различаются в зависимости от настройки. Бизнес может иметь более формальную форму, чем интернет-кафе.
- Предприятию может потребоваться определенный формат даты или времени для всей организации.
- Разные версии одной и той же настраиваемой культуры или культуры, настраиваемой на одном компьютере, и культуры только для Windows на другом.
Поэтому, если вы отформатируете строку с определенным форматом даты / времени, а затем попытаетесь проанализировать ее позже, синтаксический анализ может завершиться неудачно, если версия изменилась, если изменился компьютер, если изменилась версия платформы (более новые данные) или если пользовательская культура был изменен. Если вам нужно сохранить данные в надежном формате, выберите двоичный метод, укажите свой собственный формат или используйте InvariantCulture.
Даже без изменения данных не забывайте использовать Invariant. Если у вас другой. и, синтаксис для чего-то вроде 1,000.29, тогда Parsing может запутаться, если клиент ожидал 1.000,29. Я видел эту проблему с приложениями, которые не понимали, что культура пользователя будет отличаться от культуры разработчика. Использование инварианта или другой техники решает эту проблему.
Конечно, вы не можете иметь одновременно «правильное» отображение для текущего пользователя и идеальное круговое переключение при изменении данных культуры. Поэтому обычно я бы рекомендовал сохранять данные с использованием InvariantCulture или другого неизменяемого формата и всегда использовать соответствующие API форматирования для отображения. У вашего приложения будут свои требования, поэтому внимательно их рассмотрите.
Обратите внимание, что для сопоставления (порядок сортировки / сравнения) даже инвариантное поведение может измениться. Вам нужно будет использовать управление версиями сортировки, чтобы обойти это, если вам нужны стабильные порядки сортировки.
Если вам нужно автоматически анализировать данные, отформатированные для удобства использования, есть два подхода:
- Разрешить пользователю явно указывать используемый формат.
- Сначала удалите из строки все символы, кроме цифр, знака минус и десятичного разделителя, прежде чем пытаться проанализировать это. Обратите внимание, что вам сначала нужно знать правильный десятичный разделитель. Невозможно угадать это правильно, и неправильное угадывание может привести к серьезным проблемам.
По возможности старайтесь избегать анализа чисел, отформатированных для удобства пользователя. Вместо этого по возможности старайтесь запрашивать числа в строго определенном (инвариантном) формате.