Пространство имен System.Globalization

57

В пространстве имен System.Globalization содержатся все классы культур и регионов, которые необходимо использовать для обеспечения поддержки различных форматов дат, чисел и даже различных календарей (классы GregorianCalendar, HebrewCalendar, JapaneseCalendar и т.д.). С помощью этих классов можно обеспечить отображение данных в различных представлениях в соответствии с локальными настройками пользователя.

Кодировка Unicode

Символ Unicode занимает 16 бит, поэтому получается, что в этой кодировке есть место для 65 536 символов. Является ли это количество достаточным для всех языков, которые в настоящее время применяются в информационных технологиях? В случае китайского языка, например, требуется свыше 80 000 символов. Однако кодировка Unicode была разработана так, чтобы справиться с этой проблемой. В Unicode необходимо различать базовые и комбинированные символы. В один базовый символ можно добавить множество комбинированных символов и тем самым получить единственный отображаемый символ или элемент.

Возьмем, к примеру, исландский символ Ogonek. Его можно получить за счет объединения базового символа 0x006F (представляющего маленькую латинскую букву "о") с комбинированными символом 0x0328 (представляющим сам символ Ogonek) и 0x0304 (представляющий комбинированный знак долготы над гласными — Macron). Комбинированные символы определяются в диапазоне от 0x0300 до 0x0345. Для рынков Америки и Европы существуют предопределенные символы, облегчающие работу со специальными символами. Символ Ogonek, например, может также получаться и за счет применения одного предопределенного символа OxO1ED.

Для азиатского рынка, где только один китайский язык требует свыше 80 000 символов, таких предопределенных символов не существует. В случае азиатских языков всегда используются комбинированные символы. В связи с этим возникает проблема с получением правильного количества отображаемых символов или текстовых элементов, а также базовых символов вместо комбинированных. В пространстве имен System.Globalization предлагается класс StringInfо, который позволяет решить эту проблему.

Ниже перечислены статические методы класса StringInfo, которые помогают работать с комбинированными символами:

GetNextTextElement

Возвращает первый текстовый элемент (базовый символ и все комбинированные) из указанной строки.

GetTextElementEnumerator

Возвращает объект TextElementEnumerator, который позволяет производить итерацию по всем текстовым элементам в строке.

ParseCombiningCharacters

Возвращает массив целых чисел, ссылающихся на все базовые символы в строке.

В одном отображаемом символе может содержаться множество символов Unicode. Во избежание проблем с этим, при написании приложений, предназначенных для международного рынка, не следует применять тип данных char, а использовать вместо него тип string, потому что в нем может размещаться текстовый элемент, содержащий как базовые, так и комбинированные символы, а в char — нет.

Культуры и регионы

Мир поделен на множество культур и регионов, и приложения должны уметь распознавать эти культурные и региональные различия. Под культурой в программировании подразумевается набор предпочтений, отражающих языковые и культурные традиции пользователя. В документе RFC 1766 (www.ietf.org/rfc/rfc1766.txt) содержится полный список наименований культур, которые применяются по всему миру, в зависимости от языка и страны или региона. В качестве примера можно упомянуть en-AU, en-CA, en-GB и en-US для английского языка в Австралии, Канаде, Великобритании и Соединенных Штатах соответственно.

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

Класс RegionInfo позволяет представлять региональные особенности (такие как валюта), а также указывать, применяется ли в регионе метрическая система. В некоторых регионах может использоваться сразу несколько языков. Одним из примеров является регион Испании, в котором есть баскская (eu-ES), каталонская (ca-ES), испанская (es-ES) и галисийская (gl-ES) культуры.

Подобно тому, как в одном регионе может использоваться множество языков, на одном языке могут говорить во множестве регионов, например, на испанском говорят в Мексике, Испании, Гватемале, Аргентине, Перу, и не только.

Специфические, нейтральные и инвариантные культуры

При применении культур в .NET Framework необходимо различать специфические, нейтральные и инвариантные культуры.

Специфические культуры ассоциируются с реальными существующими культурами, которые перечислены в упомянутом в предыдущем разделе документе RFC 1766. Они могут отображаться на нейтральные культуры. Например, de может служить нейтральной версией для таких специфических культур, как de-AT, de-DE, de-CH и т.д. de представляет собой сокращенное обозначение немецкого языка, a AT, DE и СН — сокращенное обозначение таких стран, как Австрия, Германия и Швейцария.

При переводе приложений выполнять перевод для каждого региона обычно не требуется, поскольку между вариантами немецкого языка, применяемого в Германии и Австрии, например, никакой особой разницы не существует. Поэтому вместо специфических культур для локализации приложений, как правило, достаточно использовать и просто нейтральные культуры.

Инвариантные культуры не зависят от реальных культур. При сохранении форматированных чисел и дат в файлах или отправке их по сети на сервер использование культуры, не зависящей ни от каких параметров пользователя, является наилучшим вариантом.

На рисунке показано, как выглядят отношения между этими типами культур:

Отношения между культурами разных типов

CurrentCulture и CurrentUICulture

При настройке культур необходимо проводить различие между культурой, которая должна использоваться для пользовательской интерфейса, и той, что должна применяться для форматирования чисел и дат. Все культуры ассоциируются с потоком, и наличие этих двух типов культур, соответственно, означает, что к потоку могут применяться два параметра культуры. Класс Thread имеет свойства CurrentCulture и CurrentUICulture. Свойство CurrentCulture предназначено для указания культуры, которая должна использоваться для форматирования и сортировки, а свойство CurrentUICulture — той, что должна применяться для языка пользовательского интерфейса.

Пользователи могут изменять предлагаемое по умолчанию значение для CurrentCulture с помощью опций, предлагаемых в доступной через окно панели управления оснастке Regional and Language Options (Язык и региональные стандарты). С помощью этих опций также можно изменять предлагаемые по умолчания значения для формата чисел, времени и дат.

Значение CurrentUICulture от этих опций не зависит. Оно зависит от языка операционной системы. Хотя есть одно исключение: в случае установки Windows 7, Windows Vista или Windows ХР с многоязыковым пользовательским интерфейсом (MUI) язык пользовательского интерфейса может изменяться с помощью настроек региональных стандартов, и в таком случае они будут влиять на значение свойства CurrentUICulture.

Все эти настройки обеспечивают очень хорошее поведение по умолчанию, которое в большинстве случаев изменять не требуется. При необходимости, однако, параметры культуры можно легко модифицировать, изменяя значения обоих отвечающих за культуру свойств потока, скажем, таким образом, чтобы они представляли испанскую культуру, как показано в следующем фрагменте кода:

System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("es-ES");
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;

Теперь, когда понятно, как устанавливать культуру, можно рассмотреть вопросы, связанные с форматированием чисел и дат, на которое оказывает влияние параметр CurrentCulture.

Форматирование чисел

Числовые структуры Int16, Int32, Int64 и т.д. в пространстве имен System имеют перегруженные версии метода ToString(). Этот метод может применяться для создания различных представлений чисел в зависимости от локальных настроек. В случае структуры Int32 ToString() он имеет четыре таких перегруженных версии:

public string ToString();
public string ToString(IFormatProvider);
public string ToString(string);
public string ToString(string, IFormatProvider);

В версии без аргументов ToString() возвращает строку без всяких возможных вариантов форматирования. Однако этот метод может также принимать строку и класс, реализующий интерфейс IFormatProvider.

В строке указывается желаемый формат представления данных. Этот формат может представлять собой как стандартную, так и шаблонную строку форматирования чисел. В первом случае используются предопределенные обозначения: С — формат валюты; D — десятичный формат; Е — научный формат; F — формат с фиксированной точкой; G — общий формат; N — числовой формат; X — шестнадцатеричный формат.

В шаблонной строке можно задавать количество разрядов, разделители групп и дробной части, обозначение процентов и т.д. Например, шаблонная строка форматирования вида ###.### означает, что вывод должен генерироваться в формате трехзначных десятичных блоков с разделителем групп.

Интерфейс IFormatProvider реализован классами NumberFormatInfо, DateTimeFormatInfо и CultureInfo. Этот интерфейс имеет единственный метод GetFormat(), который возвращает объект формата.

Класс NumberFormatInfo может применяться для определения специализированных форматов для чисел. В случае применения в нем конструктора по умолчанию создается независимый от культуры или инвариантный объект. С помощью свойства NumberFormatInfo можно изменять все опции форматирования, например знак положительных чисел, символ процента, разделитель групп чисел, символ валюты и многое другое. Статическое свойство InvariantInfо возвращает доступный только для чтения, независимый от культуры объект NumberFormatInfo, а статическое свойство CurrentInfo — объект NumberFormatInfo, в котором значения форматирования основаны на значениях свойства CultureInfo текущего потока.

Создадим простой консольный проект. В этом проекте первый пример демонстрирует отображение числа в формате культуры текущего потока. Во втором примере используется метод ToString() с аргументом IFormatProvider. Класс CultureInfo реализует интерфейс IFormatProvider, поэтому далее создается объект CultureInfo с использованием культуры French. И, наконец, в третьем примере демонстрируется изменение культуры текущего потока. Здесь культура изменяется на German с помощью свойства CurrentCulture экземпляра Thread:

using System;
using System.Globalization;
using System.Threading;

namespace NumberAndDateFormatting
{
    class Program
    {
        static void Main(string[] args)
        {
            NumberFormatDemo();
        }
        
        private static void NumberFormatDemo()
        {
            int val = 1234567890;

            // Культура текущего потока
            Console.WriteLine(val.ToString("N"));

            // Интерфейс IFormatProvider
            Console.WriteLine(val.ToString("N", new CultureInfo("fr-FR")));

            // Изменение культуры потока
            Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
            Console.WriteLine(val.ToString("N"));
        }
    }
}
Пройди тесты
Лучший чат для C# программистов