System.Globalization.CultureInfo.CurrentCulture 属性

本文提供了此 API 参考文档的补充说明。

CultureInfo属性及其关联对象返回CurrentCulture的对象确定日期、时间、数字和货币值的默认格式、文本排序顺序、大小写约定和字符串比较。

当前区域性是执行线程的属性。 将此属性设置为 CultureInfo 表示新区域性的对象时,该属性的值 Thread.CurrentThread.CurrentCulture 也会更改。 但是,我们建议始终使用 CultureInfo.CurrentCulture 属性来检索和设置当前区域性。

CultureInfo此属性返回的对象是只读的。 这意味着不能通过更改 DateTimeFormat现有对象来改变现有对象。 若要更改日期时间格式或当前区域性的一些其他方面,请创建新 CultureInfo 对象并将其分配给属性。

如何确定线程的区域性

启动线程时,其区域性最初确定如下:

  • 通过检索由 DefaultThreadCurrentCulture 执行线程的应用程序域中的属性指定的区域性(如果属性值不是 null)。

  • 如果线程是正在执行基于任务的异步操作的线程池线程,则其区域性由调用线程的区域性确定。 以下示例将当前区域性更改为葡萄牙语(巴西),并启动六个任务,其中每个任务显示其线程 ID、任务 ID 和当前区域性。 每个任务(和线程)都继承了调用线程的区域性。

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Runtime.Versioning;
    using System.Threading;
    using System.Threading.Tasks;
    
    public class Example14
    {
        public static async Task Main()
        {
            var tasks = new List<Task>();
            Console.WriteLine("The current culture is {0}",
                              Thread.CurrentThread.CurrentCulture.Name);
            Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
            // Change the current culture to Portuguese (Brazil).
            Console.WriteLine("Current culture changed to {0}",
                              Thread.CurrentThread.CurrentCulture.Name);
            Console.WriteLine("Application thread is thread {0}",
                              Thread.CurrentThread.ManagedThreadId);
            // Launch six tasks and display their current culture.
            for (int ctr = 0; ctr <= 5; ctr++)
                tasks.Add(Task.Run(() =>
                {
                    Console.WriteLine("Culture of task {0} on thread {1} is {2}",
                                      Task.CurrentId,
                                      Thread.CurrentThread.ManagedThreadId,
                                      Thread.CurrentThread.CurrentCulture.Name);
                }));
    
            await Task.WhenAll(tasks.ToArray());
        }
    }
    // The example displays output like the following:
    //     The current culture is en-US
    //     Current culture changed to pt-BR
    //     Application thread is thread 9
    //     Culture of task 2 on thread 11 is pt-BR
    //     Culture of task 1 on thread 10 is pt-BR
    //     Culture of task 3 on thread 11 is pt-BR
    //     Culture of task 5 on thread 11 is pt-BR
    //     Culture of task 6 on thread 11 is pt-BR
    //     Culture of task 4 on thread 10 is pt-BR
    
    Imports System.Globalization
    Imports System.Threading
    
    Module Example1
        Public Sub S1()
            Dim tasks As New List(Of Task)
            Console.WriteLine("The current culture is {0}",
                            Thread.CurrentThread.CurrentCulture.Name)
            Thread.CurrentThread.CurrentCulture = New CultureInfo("pt-BR")
            ' Change the current culture to Portuguese (Brazil).
            Console.WriteLine("Current culture changed to {0}",
                            Thread.CurrentThread.CurrentCulture.Name)
            Console.WriteLine("Application thread is thread {0}",
                            Thread.CurrentThread.ManagedThreadId)
            ' Launch six tasks and display their current culture.
            For ctr As Integer = 0 To 5
                tasks.Add(Task.Run(Sub()
                                       Console.WriteLine("Culture of task {0} on thread {1} is {2}",
                                                     Task.CurrentId,
                                                     Thread.CurrentThread.ManagedThreadId,
                                                     Thread.CurrentThread.CurrentCulture.Name)
                                   End Sub))
            Next
            Task.WaitAll(tasks.ToArray())
        End Sub
    End Module
    ' The example displays output like the following:
    '     The current culture is en-US
    '     Current culture changed to pt-BR
    '     Application thread is thread 9
    '     Culture of task 2 on thread 11 is pt-BR
    '     Culture of task 1 on thread 10 is pt-BR
    '     Culture of task 3 on thread 11 is pt-BR
    '     Culture of task 5 on thread 11 is pt-BR
    '     Culture of task 6 on thread 11 is pt-BR
    '     Culture of task 4 on thread 10 is pt-BR
    

    有关详细信息,请参阅 区域性和基于任务的异步操作

  • 通过在 Windows 上调用GetUserDefaultLocaleName函数或 ICU 中的uloc_getDefault函数,该函数当前在类似 Unix 的系统上调用具有类别LC_MESSAGES的 POSIX setlocale 函数。

请注意,如果设置与系统安装区域性或用户的首选区域性不同的特定区域性,并且应用程序启动多个线程,则这些线程的当前区域性将是函数返回 GetUserDefaultLocaleName 的区域性 DefaultThreadCurrentCulture ,除非为执行线程的应用程序域中的属性分配区域性。

有关如何确定线程区域性的详细信息,请参阅参考页中的 CultureInfo “区域性和线程”部分。

获取当前区域性

CultureInfo.CurrentCulture 属性是每线程设置;也就是说,每个线程可以有自己的区域性。 通过检索属性的值来获取当前线程的 CultureInfo.CurrentCulture 区域性,如以下示例所示。

using System;
using System.Globalization;

public class Example5
{
   public static void Main()
   {
      CultureInfo culture = CultureInfo.CurrentCulture;
      Console.WriteLine("The current culture is {0} [{1}]",
                        culture.NativeName, culture.Name);
   }
}
// The example displays output like the following:
//       The current culture is English (United States) [en-US]
Imports System.Globalization

Module Example3
    Public Sub S1()
        Dim culture As CultureInfo = CultureInfo.CurrentCulture
        Console.WriteLine("The current culture is {0} [{1}]",
                        culture.NativeName, culture.Name)
    End Sub
End Module
' The example displays output like the following:
'     The current culture is English (United States) [en-US]

显式设置 CurrentCulture 属性

若要更改现有线程使用的区域性,请将该 CultureInfo.CurrentCulture 属性设置为新区域性。 如果以这种方式显式更改线程的区域性,则当线程跨越应用程序域边界时,该更改将保持不变。 以下示例将当前线程区域性更改为荷兰(荷兰)。 它还显示,当当前线程跨越应用程序域边界时,其当前区域性将保持不变。

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

public class Info11 : MarshalByRefObject
{
    public void ShowCurrentCulture()
    {
        Console.WriteLine("Culture of {0} in application domain {1}: {2}",
                          Thread.CurrentThread.Name,
                          AppDomain.CurrentDomain.FriendlyName,
                          CultureInfo.CurrentCulture.Name);
    }
}

public class Example11
{
    public static void Main()
    {
        Info11 inf = new Info11();
        // Set the current culture to Dutch (Netherlands).
        Thread.CurrentThread.Name = "MainThread";
        CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL");
        inf.ShowCurrentCulture();

        // Create a new application domain.
        AppDomain ad = AppDomain.CreateDomain("Domain2");
        Info11 inf2 = (Info11)ad.CreateInstanceAndUnwrap(typeof(Info11).Assembly.FullName, "Info11");
        inf2.ShowCurrentCulture();
    }
}
// The example displays the following output:
//       Culture of MainThread in application domain ChangeCulture1.exe: nl-NL
//       Culture of MainThread in application domain Domain2: nl-NL
Imports System.Globalization
Imports System.Threading

Public Class Info : Inherits MarshalByRefObject
   Public Sub ShowCurrentCulture()
      Console.WriteLine("Culture of {0} in application domain {1}: {2}",
                        Thread.CurrentThread.Name,
                        AppDomain.CurrentDomain.FriendlyName,
                        CultureInfo.CurrentCulture.Name)
   End Sub
End Class

Module Example2
    Public Sub S1()
        Dim inf As New Info()
        ' Set the current culture to Dutch (Netherlands).
        Thread.CurrentThread.Name = "MainThread"
        CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL")
        inf.ShowCurrentCulture()

        ' Create a new application domain.
        Dim ad As AppDomain = AppDomain.CreateDomain("Domain2")
        Dim inf2 As Info = CType(ad.CreateInstanceAndUnwrap(GetType(Info).Assembly.FullName, "Info"),
                          Info)
        inf2.ShowCurrentCulture()
    End Sub
End Module
' This example displays the following output:
'       Culture of MainThread in application domain Example.exe: nl-NL
'       Culture of MainThread in application domain Domain2: nl-NL

注意

使用 CultureInfo.CurrentCulture 属性更改区域性需要具有 SecurityPermission 设置值的权限 ControlThread 。 由于与线程关联的安全状态,操作线程是危险的。 因此,此权限应仅提供给可信代码,然后仅在必要时提供。 不能在半受信任的代码中更改线程区域性。

从 .NET Framework 4 开始,可以将当前线程区域性显式更改为特定区域性(如法语(如法语)或中性文化(如法语)。 CultureInfo当对象表示中性区域性时,属性的值CultureInfo(例如CalendarCompareInfoDateTimeFormatNumberFormatTextInfo反映与中性区域性关联的特定区域性。 例如,英语中性文化的主要文化是英语(美国);德国文化的主要文化是德语(德国)。 以下示例演示当前区域性设置为特定区域性、法语(加拿大)和中性区域性(法语)时格式设置的差异。

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

public class Example12
{
   public static void Main()
   {
      double value = 1634.92;
      CultureInfo.CurrentCulture = new CultureInfo("fr-CA");
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("{0:C2}\n", value);

      Thread.CurrentThread.CurrentCulture = new CultureInfo("fr");
      Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("{0:C2}", value);
   }
}
// The example displays the following output:
//       Current Culture: fr-CA
//       1 634,92 $
//
//       Current Culture: fr
//       1 634,92 €
Imports System.Globalization
Imports System.Threading

Module Example4
    Public Sub S1()
        Dim value As Double = 1634.92
        CultureInfo.CurrentCulture = New CultureInfo("fr-CA")
        Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name)
        Console.WriteLine("{0:C2}", value)
        Console.WriteLine()

        Thread.CurrentThread.CurrentCulture = New CultureInfo("fr")
        Console.WriteLine("Current Culture: {0}",
                        CultureInfo.CurrentCulture.Name)
        Console.WriteLine("{0:C2}", value)
    End Sub
End Module
' The example displays the following output:
'       Current Culture: fr-CA
'       1 634,92 $
'       
'       Current Culture: fr
'       1 634,92 €

还可以将 CultureInfo.CurrentCulture 属性与属性一起使用 HttpRequest.UserLanguages ,将 ASP.NET 应用程序的属性设置为 CurrentCulture 用户的首选区域性,如以下示例所示。

CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(Request13.UserLanguages[0]);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages(0))

当前区域性和用户替代

Windows 允许用户在控制面板中使用区域和语言选项替代对象及其关联对象的标准属性值CultureInfo。 属性 CultureInfo 返回 CurrentCulture 的对象在以下情况下反映这些用户替代:

  • 如果当前线程区域性由 Windows GetUserDefaultLocaleName 函数隐式设置。

  • 如果该属性定义的 DefaultThreadCurrentCulture 当前线程区域性对应于当前的 Windows 系统区域性。

  • 如果当前线程区域性显式设置为方法返回的 CreateSpecificCulture 区域性,并且该区域性对应于当前的 Windows 系统区域性。

  • 如果将当前线程区域性显式设置为构造函数实例化的 CultureInfo(String) 区域性,并且该区域性对应于当前的 Windows 系统区域性。

在某些情况下,尤其是对于服务器应用程序,将当前区域性设置为 CultureInfo 反映用户替代的对象可能是不可取的。 相反,可以将当前区域性设置为 CultureInfo 不以以下方式反映用户替代的对象:

当前区域性和 UWP 应用

在通用 Windows 平台(UWP)应用中,该属性是读写的CurrentCulture,就像在 .NET Framework 和 .NET Core 应用中一样;你可以使用它来获取和设置当前区域性。 但是,UWP 应用不区分当前区域性和当前 UI 区域性。 CurrentCultureCurrentUICulture 属性映射到 Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages 集合中的第一个值。

在 .NET Framework 和 .NET Core 应用中,当前区域性是每线程设置,并且 CurrentCulture 该属性仅反映当前线程的区域性。 在 UWP 应用中,当前区域性映射到 Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages 属性,该属性是全局设置。 CurrentCulture设置属性会更改整个应用的区域性;区域性不能按线程设置。