Поделиться через


Класс CultureInfo

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Класс CultureInfo предоставляет сведения, связанные с определенной культурой, такие как язык, подязык, страна/регион, календарь и соглашения. Этот класс также предоставляет доступ к экземплярам, зависящим от культурных особенностей, таких как объекты DateTimeFormatInfo, NumberFormatInfo, CompareInfo, и TextInfo. Эти объекты содержат сведения, необходимые для операций, зависящих от языка и региональных параметров, таких как изменение регистра, форматирование дат и чисел, а также сравнение строк. Класс CultureInfo используется напрямую или косвенно классами, которые форматируют, анализируют или управляют данными, специфичными для культуры, например String, DateTime, DateTimeOffset и числовыми типами.

Имена и идентификаторы культур

Класс CultureInfo задает уникальное имя для каждой культуры на основе RFC 4646. Название представляет собой сочетание двухбуквенного или трехбуквенного кода ISO 639 в нижнем регистре, связанного с языком, и двухбуквенного кода ISO 3166 в верхнем регистре, связанного со страной или регионом. Кроме того, для приложений, работающих под управлением Windows 10 или более поздних версий, поддерживаются имена культур, соответствующие допустимым тегам языка BCP-47.

Примечание.

Если название культуры передается конструктору класса или методу, например CreateSpecificCulture или CultureInfo, его регистр не имеет значения.

Формат имени для культуры на основе RFC 4646 — это languagecode2-country/regioncode2, где languagecode2 — это код языка из двух букв, а country/regioncode2 — двухбуквенный код субкультуры. Примеры включают ja-JP японский (Япония) и en-US английский (США). В случаях, когда двухбуквенный языковой код недоступен, используется трехбуквенный код, определенный в ISO 639-3.

Некоторые языковые коды и параметры культур также указывают письменность ISO 15924. Например, Cyrl указывает кириллический скрипт и латн указывает латинский скрипт. Название культуры, включающее письменность, использует шаблон languagecode2-scripttag-country/regioncode2. Примером этого типа имени культуры является uz-Cyrl-UZ для узбекского (кириллица, Узбекистан). В операционных системах Windows до Windows Vista название культуры, включающее скрипт, использует шаблонlanguagecode2-country/regioncode2-scripttag, например, uz-UZ-Cyrl для узбекского (кириллица, Узбекистана).

Нейтральная культура задается только двухбуквенным строчным кодом языка. Например, fr задает нейтральную культуру для французского языка, а de — для немецкого языка.

Примечание.

Существуют два наименования культур, которые противоречат этому правилу. Языки и региональные параметры: китайский (упрощенное письмо), именованный zh-Hans, и китайский (традиционное письмо), именованный zh-Hant, — это нейтральные культуры. Названия культур представляют собой текущий стандарт и должны использоваться, если у вас нет причины использовать старые названия zh-CHS и zh-CHT.

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

Некоторые предопределенные имена культур и их идентификаторы используются этим и другими классами в пространстве имен System.Globalization. Подробные сведения о языковых и региональных параметрах для систем Windows см. в столбце Тега языка в списке языков и регионов, поддерживаемых Windows. Названия культур следуют стандарту, определенному BCP 47.

Имена и идентификаторы культур представляют только подмножество культур, которые можно найти на определенном компьютере. Версии Windows или пакеты обновления могут изменить доступные региональные параметры. Приложения могут добавлять пользовательские культуры, используя класс CultureAndRegionInfoBuilder. Пользователи могут добавлять пользовательские региональные параметры с помощью средства Microsoft Locale Builder. Microsoft Locale Builder написан на управляемом коде с использованием класса CultureAndRegionInfoBuilder.

Несколько различных имен тесно связаны с культурой, особенно с именами, связанными со следующими членами класса:

Инвариантные, нейтральные и конкретные культуры

Языки и культуры обычно группируются в три набора: инвариантные, нейтральные и специфические культуры.

Инвариантная культура не зависит от культурных различий. Ваше приложение указывает инвариантную культуру по имени с помощью пустой строки ("") или по её идентификатору. InvariantCulture определяет экземпляр инвариантной культуры. Он связан с английским языком, но не с какой-либо страной или регионом. Он используется практически в любом методе в пространстве имен Globalization, требующем указания культуры.

Нейтральная культура — это культура, ассоциирующаяся с языком, но не со страной или регионом. Конкретная культура — это культура, связанная с языком и страной/регионом. Например, fr это нейтральное имя для французского языка и fr-FR является именем конкретной французской культуры (Франция). Обратите внимание, что упрощённый китайский и традиционный китайский также считаются нейтральными вариантами культур.

Создание экземпляра класса для нейтральной культуры не рекомендуется, так как его данные являются произвольными. Чтобы отобразить и отсортировать данные, укажите язык и регион. Кроме того, свойство Name объекта, созданного для нейтральной CompareInfo культуры, возвращает только страну и не включает регион.

Определенные культуры имеют иерархическую структуру: родителем конкретной культуры является нейтральная культура, а родителем нейтральной культуры является инвариантная культура. Свойство Parent содержит нейтральную культуру, связанную с определенной культурой. Пользовательские культуры должны определять Parent свойство в соответствии с этим шаблоном.

Если ресурсы для определенной культуры недоступны в операционной системе, используются ресурсы для связанной нейтральной культуры. Если ресурсы для нейтральной культуры недоступны, используются ресурсы, внедренные в основную сборку. Для получения дополнительной информации о процессе резервного копирования ресурсов см. в разделе "Упаковка и развертывание ресурсов".

Список локалей в API Windows немного отличается от списка культур, поддерживаемых .NET. Если требуется взаимодействие с Windows, например, через механизм p/invoke, приложение должно использовать определенную культуру, определенную операционной системой. Использование конкретных языковых и региональных параметров обеспечивает согласованность с эквивалентным языковым стандартом Windows, который определяется идентификатором, совпадающим с LCID.

Элемент DateTimeFormatInfo или NumberFormatInfo может быть создан только для инвариантной культуры или для конкретных культур, но не для нейтральных культур.

Если DateTimeFormatInfo.Calendar является TaiwanCalendar, но Thread.CurrentCulture не установлено на zh-TW, то DateTimeFormatInfo.NativeCalendarName, DateTimeFormatInfo.GetEraName и DateTimeFormatInfo.GetAbbreviatedEraName возвращают пустую строку ("").

Пользовательские культуры

В Windows можно создавать пользовательские локали. Дополнительные сведения см. в разделе "Пользовательские локали".

CultureInfo и культурные данные

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

  • Во всех версиях .NET (Core), работающих на платформах Unix или Windows 10 и более поздних версиях, культурные данные предоставляются библиотекой международных компонентов Юникода (ICU). Конкретная версия библиотеки ICU зависит от отдельной операционной системы.
  • Во всех версиях .NET (Core), работающих в Windows 9 и более ранних версиях, региональные данные предоставляются операционной системой Windows.
  • В .NET Framework 4 и более поздних версиях региональные данные предоставляются операционной системой Windows.

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

Некоторые CultureInfo объекты различаются в зависимости от базовой платформы. В частности, zh-CN, или китайский (упрощённый, Китай) и zh-TW, или китайский (традиционные, Тайвань), доступны как языки и региональные параметры в системах Windows, но они являются алиасами в системах Unix. "zh-CN" является псевдонимом для культуры "zh-Hans-CN", и "zh-TW" является псевдонимом для культуры "zh-Hant-TW". Псевдонимированные культуры не возвращаются вызовами метода GetCultures и могут иметь разные значения свойств, включая отличные культуры Parent, по сравнению с их эквивалентами в Windows. Для культур zh-CN и zh-TW эти различия включают следующее:

  • В системах Windows родительский язык культуры "zh-CN" — "zh-Hans", а родительский язык культуры "zh-TW" — "zh-Hant". Родительская культура обоих этих культур — "zh". В системах Unix родители обоих культур являются "zh". Это означает, что если вы не предоставляете ресурсы для культур "zh-CN" или "zh-TW", но вы предоставляете ресурсы для нейтральной культуры "zh-Hans" или "zh-Hant", то ваше приложение будет загружать ресурсы для нейтральной культуры в Windows, но не в Unix. В системах Unix необходимо явно задать для потока CurrentUICulture значение "zh-Hans" или "zh-Hant".

  • В системах Windows, вызывая CultureInfo.Equals для экземпляра, представляющего культуру "zh-CN", и передавая в него экземпляр "zh-Hans-CN", возвращается true. В системах Unix вызов метода возвращается false. Это поведение также относится к вызову Equals на экземпляре "zh-TW" CultureInfo и передаче ему экземпляра "zh-Hant-Tw".

Динамические данные культурных настроек

За исключением инвариантной культуры, данные о культуре являются динамическими. Это верно даже для предопределенных языков. Например, страны или регионы принимают новые валюты, изменяют орфографию слов или изменяют предпочитаемый календарь, а определения языка и региональных параметров изменяются для отслеживания этого. Пользовательские культуры могут изменяться без уведомления, а любая конкретная культура может быть переопределена пользовательской культурой замены. Кроме того, как описано ниже, отдельный пользователь может переопределить культурные предпочтения. Приложения всегда должны получать культурные данные во время выполнения.

Внимание

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

Текущая культура и текущая культура пользовательского интерфейса

Каждый поток в приложении .NET имеет текущие региональные параметры и параметры пользовательского интерфейса. Текущая культура определяет форматы дат, времени, чисел и валютных значений, порядок сортировки текста, соглашения о регистре и методы сравнения строк. Текущая культура пользовательского интерфейса используется для получения ресурсов, соответствующих культуре, в процессе выполнения.

Примечание.

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

Дополнительные сведения о текущей культуре см. в свойстве CultureInfo.CurrentCulture. Для получения более подробной информации о текущей культуре пользовательского интерфейса см. тему свойства CultureInfo.CurrentUICulture.

Получение текущих и текущих региональных параметров пользовательского интерфейса

Вы можете получить объект CultureInfo, представляющий текущую культуру, двумя способами:

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

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

public class CurrentCultureEx
{
    public static void Main()
    {
        CultureInfo culture1 = CultureInfo.CurrentCulture;
        CultureInfo culture2 = Thread.CurrentThread.CurrentCulture;
        Console.WriteLine($"The current culture is {culture1.Name}");
        Console.WriteLine($"The two CultureInfo objects are equal: {culture1 == culture2}");
    }
}
// The example displays output like the following:
//     The current culture is en-US
//     The two CultureInfo objects are equal: True

Вы можете получить объект, представляющий текущую культурную среду пользовательского интерфейса CultureInfo, двумя возможными способами:

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

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

public class CurrentUIEx
{
    public static void Main()
    {
        CultureInfo uiCulture1 = CultureInfo.CurrentUICulture;
        CultureInfo uiCulture2 = Thread.CurrentThread.CurrentUICulture;
        Console.WriteLine($"The current UI culture is {uiCulture1.Name}");
        Console.WriteLine($"The two CultureInfo objects are equal: {uiCulture1 == uiCulture2}");
    }
}
// The example displays output like the following:
//     The current UI culture is en-US
//     The two CultureInfo objects are equal: True

Настройка текущих и текущих региональных параметров пользовательского интерфейса

Чтобы изменить культуру и UI-культуру потока, выполните следующие действия:

  1. Создайте экземпляр объекта CultureInfo, представляющего эту культуру, вызвав конструктор класса CultureInfo и передав ему название культуры. Конструктор CultureInfo(String) создает экземпляр объекта CultureInfo, который отражает пользовательские переопределения, если новые язык и региональные параметры совпадают с текущими языком и региональными параметрами Windows. Конструктор CultureInfo(String, Boolean) позволяет указать, следует ли новому экземпляру объекта CultureInfo учитывать пользовательские переопределения, если новая культура совпадает с текущей культурой Windows.

  2. Назначьте объект свойству CultureInfo.CurrentCulture или CultureInfo.CurrentUICulture на .NET Core и платформе .NET Framework версии 4.6 и более поздние.

В следующем примере извлекается текущая культура. Если это что-либо, кроме культуры французского (Франция), изменяется текущая культура на французскую (Франция). В противном случае она изменяет текущую культуру на французский (Люксембург).

using System;
using System.Globalization;

public class ChangeEx1
{
    public static void Main()
    {
        CultureInfo current = CultureInfo.CurrentCulture;
        Console.WriteLine($"The current culture is {current.Name}");
        CultureInfo newCulture;
        if (current.Name.Equals("fr-FR"))
            newCulture = new CultureInfo("fr-LU");
        else
            newCulture = new CultureInfo("fr-FR");

        CultureInfo.CurrentCulture = newCulture;
        Console.WriteLine($"The current culture is now {CultureInfo.CurrentCulture.Name}");
    }
}
// The example displays output like the following:
//     The current culture is en-US
//     The current culture is now fr-FR

В следующем примере извлекается текущая культура. Если это не словенская культура (Словения), она изменяет текущую культуру на словенскую (Словения). В противном случае она изменяет текущую культуру на хорватской (Хорватия).

using System;
using System.Globalization;

public class ChangeUICultureEx
{
    public static void Main()
    {
        CultureInfo current = CultureInfo.CurrentUICulture;
        Console.WriteLine($"The current UI culture is {current.Name}");
        CultureInfo newUICulture;
        if (current.Name.Equals("sl-SI"))
            newUICulture = new CultureInfo("hr-HR");
        else
            newUICulture = new CultureInfo("sl-SI");

        CultureInfo.CurrentUICulture = newUICulture;
        Console.WriteLine($"The current UI culture is now {CultureInfo.CurrentUICulture.Name}");
    }
}
// The example displays output like the following:
//     The current UI culture is en-US
//     The current UI culture is now sl-SI

Получение всех культур

Вы можете получить массив определенных категорий региональных параметров или всех региональных параметров, доступных на локальном компьютере, вызвав метод GetCultures. Например, можно получить пользовательские культуры, определенные культуры или нейтральные культуры как по отдельности, так и в сочетании.

В следующем примере метод GetCultures вызывается дважды: сначала с элементом перечисления System.Globalization.CultureTypes для получения всех настраиваемых культур, а затем с элементом перечисления System.Globalization.CultureTypes для получения всех замещающих культур.

using System;
using System.Globalization;

public class GetCulturesEx
{
    public static void Main()
    {
        // Get all custom cultures.
        CultureInfo[] custom = CultureInfo.GetCultures(CultureTypes.UserCustomCulture);
        if (custom.Length == 0)
        {
            Console.WriteLine("There are no user-defined custom cultures.");
        }
        else
        {
            Console.WriteLine("Custom cultures:");
            foreach (var culture in custom)
                Console.WriteLine($"   {culture.Name} -- {culture.DisplayName}");
        }
        Console.WriteLine();

        // Get all replacement cultures.
        CultureInfo[] replacements = CultureInfo.GetCultures(CultureTypes.ReplacementCultures);
        if (replacements.Length == 0)
        {
            Console.WriteLine("There are no replacement cultures.");
        }
        else
        {
            Console.WriteLine("Replacement cultures:");
            foreach (var culture in replacements)
                Console.WriteLine($"   {culture.Name} -- {culture.DisplayName}");
        }
        Console.WriteLine();
    }
}
// The example displays output like the following:
//     Custom cultures:
//        x-en-US-sample -- English (United States)
//        fj-FJ -- Boumaa Fijian (Viti)
//
//     There are no replacement cultures.

Культура и потоки

При запуске нового потока приложения его текущая культура и культура пользовательского интерфейса определяются текущими языковыми и региональными настройками системы, а не языковыми и региональными настройками потока. В следующем примере демонстрируется это различие. Он устанавливает текущую культуру и текущую культуру пользовательского интерфейса потока приложения на французскую культуру (Франция) (fr-FR). Если культура в данный момент уже установлена на fr-FR, в примере она меняется на английскую (США) культуру (en-US). Он отображает три случайных числа в виде значений валюты, а затем создает новый поток, который, в свою очередь, отображает три более случайных чисел в качестве значений валюты. Но, как показано в выходных данных из примера, значения валют, отображаемые новым потоком, не отражают форматы французской (Франция) культуры, в отличие от выходных данных основного потока программы.

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

public class DefaultThreadEx
{
    static Random rnd = new Random();

    public static void Main()
    {
        if (Thread.CurrentThread.CurrentCulture.Name != "fr-FR")
        {
            // If current culture is not fr-FR, set culture to fr-FR.
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR");
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("fr-FR");
        }
        else
        {
            // Set culture to en-US.
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("en-US");
        }
        ThreadProc();

        Thread worker = new Thread(ThreadProc);
        worker.Name = "WorkerThread";
        worker.Start();
    }

    private static void DisplayThreadInfo()
    {
        Console.WriteLine($"\nCurrent Thread Name: '{Thread.CurrentThread.Name}'");
        Console.WriteLine($"Current Thread Culture/UI Culture: {Thread.CurrentThread.CurrentCulture.Name}/{Thread.CurrentThread.CurrentUICulture.Name}");
    }

    private static void DisplayValues()
    {
        // Create new thread and display three random numbers.
        Console.WriteLine("Some currency values:");
        for (int ctr = 0; ctr <= 3; ctr++)
            Console.WriteLine($"   {rnd.NextDouble() * 10:C2}");
    }

    private static void ThreadProc()
    {
        DisplayThreadInfo();
        DisplayValues();
    }
}
// The example displays output similar to the following:
//       Current Thread Name: ''
//       Current Thread Culture/UI Culture: fr-FR/fr-FR
//       Some currency values:
//          8,11 €
//          1,48 €
//          8,99 €
//          9,04 €
//
//       Current Thread Name: 'WorkerThread'
//       Current Thread Culture/UI Culture: en-US/en-US
//       Some currency values:
//          $6.72
//          $6.35
//          $2.90
//          $7.72

Вы можете задать культуру и UI-культуру всех потоков в домене приложения, назначив объект CultureInfo, который представляет эту культуру, для свойств DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture. В следующем примере эти свойства используются, чтобы гарантировать, что все потоки в домене приложения по умолчанию имеют одинаковые настройки языка и региональные параметры.

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

public class SetThreadsEx
{
    static Random rnd = new Random();

    public static void Main()
    {
        if (Thread.CurrentThread.CurrentCulture.Name != "fr-FR")
        {
            // If current culture is not fr-FR, set culture to fr-FR.
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR");
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("fr-FR");
        }
        else
        {
            // Set culture to en-US.
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("en-US");
        }
        ThreadProc();

        Thread worker = new Thread(SetThreadsEx.ThreadProc);
        worker.Name = "WorkerThread";
        worker.Start();
    }

    private static void DisplayThreadInfo()
    {
        Console.WriteLine($"\nCurrent Thread Name: '{Thread.CurrentThread.Name}'");
        Console.WriteLine($"Current Thread Culture/UI Culture: {Thread.CurrentThread.CurrentCulture.Name}/{Thread.CurrentThread.CurrentUICulture.Name}");
    }

    private static void DisplayValues()
    {
        // Create new thread and display three random numbers.
        Console.WriteLine("Some currency values:");
        for (int ctr = 0; ctr <= 3; ctr++)
            Console.WriteLine($"   {rnd.NextDouble() * 10:C2}");
    }

    private static void ThreadProc()
    {
        DisplayThreadInfo();
        DisplayValues();
    }
}
// The example displays output similar to the following:
//       Current Thread Name: ''
//       Current Thread Culture/UI Culture: fr-FR/fr-FR
//       Some currency values:
//          6,83 €
//          3,47 €
//          6,07 €
//          1,70 €
//
//       Current Thread Name: 'WorkerThread'
//       Current Thread Culture/UI Culture: fr-FR/fr-FR
//       Some currency values:
//          9,54 €
//          9,50 €
//          0,58 €
//          6,91 €

Предупреждение

Хотя свойства DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture являются статическими элементами, они определяют культуру и культуру пользовательского интерфейса по умолчанию только для домена приложения, который является текущим на момент установки этих значений свойств. Для получения дополнительной информации см. следующий раздел: «Культура и домены приложений».

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

Культурные и прикладные области

DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture являются статическими свойствами, которые явно определяют культуру по умолчанию только для домена приложения, который является текущим на момент установки или извлечения значения свойства. В следующем примере устанавливаются культура и культура пользовательского интерфейса по умолчанию в домене приложения по умолчанию для французского языка (Франция), а затем используются класс AppDomainSetup и делегат AppDomainInitializer, чтобы установить культуру и культуру пользовательского интерфейса по умолчанию в новом домене приложения на русский (Россия). Затем один поток выполняет два метода в каждом домене приложения. Обратите внимание, что культура и культура пользовательского интерфейса потока не заданы явным образом; они заимствуются из культуры и культуры пользовательского интерфейса по умолчанию домена приложения, в котором выполняется поток. Обратите внимание также, что свойства DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture возвращают значения по умолчанию для CultureInfo домена приложения, который является текущим на момент вызова метода.

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
        // Set the default culture and display the current date in the current application domain.
        Info info1 = new Info();
        SetAppDomainCultures("fr-FR");

        // Create a second application domain.
        AppDomainSetup setup = new AppDomainSetup();
        setup.AppDomainInitializer = SetAppDomainCultures;
        setup.AppDomainInitializerArguments = new string[] { "ru-RU" };
        AppDomain domain = AppDomain.CreateDomain("Domain2", null, setup);
        // Create an Info object in the new application domain.
        Info info2 = (Info)domain.CreateInstanceAndUnwrap(typeof(Example).Assembly.FullName,
                                                           "Info");

        // Execute methods in the two application domains.
        info2.DisplayDate();
        info2.DisplayCultures();

        info1.DisplayDate();
        info1.DisplayCultures();
    }

    public static void SetAppDomainCultures(string[] names)
    {
        SetAppDomainCultures(names[0]);
    }

    public static void SetAppDomainCultures(string name)
    {
        try
        {
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture(name);
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture(name);
        }
        // If an exception occurs, we'll just fall back to the system default.
        catch (CultureNotFoundException)
        {
            return;
        }
        catch (ArgumentException)
        {
            return;
        }
    }
}

public class Info : MarshalByRefObject
{
    public void DisplayDate()
    {
        Console.WriteLine($"Today is {DateTime.Now:D}");
    }

    public void DisplayCultures()
    {
        Console.WriteLine($"Application domain is {AppDomain.CurrentDomain.Id}");
        Console.WriteLine($"Default Culture: {CultureInfo.DefaultThreadCurrentCulture}");
        Console.WriteLine($"Default UI Culture: {CultureInfo.DefaultThreadCurrentUICulture}");
    }
}
// The example displays the following output:
//       Today is 14 октября 2011 г.
//       Application domain is 2
//       Default Culture: ru-RU
//       Default UI Culture: ru-RU
//       Today is vendredi 14 octobre 2011
//       Application domain is 1
//       Default Culture: fr-FR
//       Default UI Culture: fr-FR

Дополнительные сведения о культурах и доменах приложений см. в разделе "Домены приложений и потоки" темы "Домены приложений".

Асинхронные операции на основе культуры и задач

Шаблон асинхронного программирования на основе задач использует объекты Task и Task<TResult> для асинхронного выполнения делегатов в потоках пулах. Конкретный поток, на котором выполняется определенная задача, заранее не известен, но определяется только во время выполнения.

Для приложений, предназначенных для платформы .NET Framework версии 4.6 или более поздней, культура является частью контекста асинхронной операции. Другими словами, асинхронные операции по умолчанию наследуют значения CurrentCulture и CurrentUICulture свойства потока, из которого они запускаются. Если текущие язык и региональные параметры или текущие параметры пользовательского интерфейса отличаются от системных, то текущие параметры переходят через границы потоков и становятся параметрами потока из пула потоков, выполняющего асинхронную операцию.

Следующий пример иллюстрирует это. В примере определяется Func<TResult> делегат, formatDelegateкоторый возвращает некоторые числа, отформатированные в виде значений валюты. Пример изменяет текущую культуру системы на французскую (Франция) или, если французская (Франция) уже является текущей культурой, английскую (Соединенные Штаты). Затем он:

  • Вызывает делегат напрямую, чтобы он выполнялся синхронно в главном потоке приложения.
  • Создает задачу, которая выполняет делегат асинхронно в пуле потоков.
  • Создает задачу, которая синхронно выполняет делегата в основном потоке приложения путем вызова метода Task.RunSynchronously.

Как показано в выходных данных из примера, при изменении текущего языка и региональных параметров на французский (Франция) текущий язык и региональные параметры потока, из которого вызываются задачи асинхронно, становится текущим языком и региональными параметрами для этой асинхронной операции.

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

public class AsyncCultureEx1
{
    public static void Main()
    {
        decimal[] values = { 163025412.32m, 18905365.59m };
        string formatString = "C2";

        string FormatDelegate()
        {
            string output = $"Formatting using the {CultureInfo.CurrentCulture.Name} " +
            "culture on thread {Thread.CurrentThread.ManagedThreadId}.\n";
            foreach (decimal value in values)
                output += $"{value.ToString(formatString)}   ";

            output += Environment.NewLine;
            return output;
        }

        Console.WriteLine($"The example is running on thread {Thread.CurrentThread.ManagedThreadId}");
        // Make the current culture different from the system culture.
        Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
        if (CultureInfo.CurrentCulture.Name == "fr-FR")
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
        else
            Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");

        Console.WriteLine($"Changed the current culture to {CultureInfo.CurrentCulture.Name}.\n");

        // Execute the delegate synchronously.
        Console.WriteLine("Executing the delegate synchronously:");
        Console.WriteLine(FormatDelegate());

        // Call an async delegate to format the values using one format string.
        Console.WriteLine("Executing a task asynchronously:");
        var t1 = Task.Run(FormatDelegate);
        Console.WriteLine(t1.Result);

        Console.WriteLine("Executing a task synchronously:");
        var t2 = new Task<string>(FormatDelegate);
        t2.RunSynchronously();
        Console.WriteLine(t2.Result);
    }
}
// The example displays the following output:
//         The example is running on thread 1
//         The current culture is en-US
//         Changed the current culture to fr-FR.
//
//         Executing the delegate synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task asynchronously:
//         Formatting using the fr-FR culture on thread 3.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €

DefaultThreadCurrentCulture и DefaultThreadCurrentUICulture являются свойствами в рамках домена приложения; то есть они устанавливают культуру по умолчанию для всех потоков, не назначенных явной культуре в определенном домене приложения. Однако для приложений, предназначенных для платформы .NET Framework 4.6 или более поздней, культура вызывающего потока остаётся частью контекста асинхронной задачи, даже если задача выходит за пределы домена приложения.

Сериализация объектов CultureInfo

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

  • Если значение свойства равно CultureTypes, и эта региональная настройка впервые появилась в определенной версии операционной системы Windows, то его нельзя десериализовать в более ранней версии Windows. Например, если культурные настройки были введены в Windows 10, их нельзя десериализовать в Windows 8.

  • Если значение CultureTypes равно CultureTypes.UserCustomCulture, и на компьютере, на котором оно десериализуется, не установлен этот пользовательский языковой стандарт, его невозможно десериализовать.

  • CultureTypes Если значение параметра равно CultureTypes.ReplacementCultures, и на компьютере, где происходит десериализация, отсутствует эта замещающая культура, оно десериализуется с тем же именем, но не с теми же всеми характеристиками. Например, если en-US является замещающей культурой на компьютере A, но не на компьютере B, и если объект CultureInfo, ссылающийся на эту культуру, сериализуется на компьютере A и десериализуется на компьютере B, то никакие пользовательские характеристики этой культуры не передаются. Культура десериализуется успешно, но с изменённым значением.

параметры переопределения панели управления

Пользователь может переопределить некоторые значения, связанные с текущими языковыми и региональными параметрами Windows, через Панель управления в разделе региональных и языковых параметров. Например, пользователь может выбрать отображение даты в другом формате или использовать валюту, отличную от валюты по умолчанию для локали. Как правило, ваши приложения должны учитывать пользовательские переопределения.

Если UseUserOverride задан true и указанный язык и региональные параметры совпадают с текущими настройками Windows, CultureInfo использует эти переопределения, включая пользовательские настройки свойств экземпляра DateTimeFormatInfo, возвращаемого свойством DateTimeFormat и свойства экземпляра NumberFormatInfo, возвращаемого свойством NumberFormat. Если параметры пользователя несовместимы с культурой, связанной с CultureInfo, например, если выбранный календарь не является одним из OptionalCalendars, результаты методов и значения свойств не определены.

Альтернативные порядки сортировки

Некоторые культуры поддерживают несколько порядков сортировки. Например:

  • Испанская культура (Испания) имеет два порядка сортировки: международный порядок сортировки и традиционный порядок сортировки. При создании экземпляра объекта с CultureInfo именем культуры используется международный es-ES порядок сортировки. При создании экземпляра объекта с CultureInfo именем культуры используется традиционный es-ES-tradnl порядок сортировки.

  • Культура zh-CN (китайский (упрощенный, Китайская Народная Республика)) поддерживает два порядка сортировки: по произношению (по умолчанию) и по числу черт. При создании экземпляра CultureInfo объекта с именем культуры zh-CN используется порядок сортировки по умолчанию. При создании экземпляра CultureInfo объекта с локальным идентификатором 0x00020804 строки сортируются по числу штрихов.

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

Имя культуры Культура Имя сортировки и идентификатор по умолчанию Альтернативное имя и идентификатор для сортировки
es-ES Испанский (Испания) Международный: 0x00000C0A Традиционное: 0x0000040A
zh-TW Китайский (Тайвань) Число штрихов: 0x00000404 Бопомофо: 0x00030404
zh-CN Китайский (КНР) Произношение: 0x00000804 Число штрихов: 0x00020804
zh-HK Китайский (специальный административный регион Гонконг) Число штрихов: 0x00000c04 Число штрихов: 0x00020c04
zh-SG китайский (Сингапур) Произношение: 0x00001004 Число штрихов: 0x00021004
zh-MO китайский (Макао, Специальный административный район) Произношение: 0x00001404 Число штрихов: 0x00021404
ja-JP Японский (Япония) По умолчанию: 0x00000411 Юникод: 0x00010411
ko-KR корейский (Корея) По умолчанию: 0x00000412 Корейский Хвансун - Юникод: 0x00010412
de-DE Немецкий (Германия) Словарь: 0x00000407 Сортировка телефонной книги DIN: 0x00010407
hu-HU Венгерский (Венгрия) По умолчанию: 0x0000040e Технический сорт: 0x0001040e
ka-GE Грузинский (Грузия) Традиционное: 0x00000437 Современная сортировка: 0x00010437

Текущая культура и приложения UWP

В приложениях для универсальной платформы Windows (UWP) свойства CurrentCulture и CurrentUICulture доступны для чтения и записи, как и в приложениях для платформ .NET Framework и .NET Core. Однако приложения UWP распознают только одну культуру. Свойства CurrentCulture и CurrentUICulture соответствуют первому значению в коллекции Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages.

В приложениях .NET текущая культура — это параметр для каждого потока, и свойства CurrentCulture и CurrentUICulture отражают только культуру и культуру пользовательского интерфейса текущего потока. В приложениях UWP текущая культура сопоставляется с коллекцией Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages, которая является глобальным параметром. Задание свойства CurrentCulture или CurrentUICulture изменяют культуру всего приложения; культура не может быть установлена для отдельного потока.