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 {Thread.CurrentThread.CurrentCulture.Name}");
            Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
            // Change the current culture to Portuguese (Brazil).
            Console.WriteLine($"Current culture changed to {Thread.CurrentThread.CurrentCulture.Name}");
            Console.WriteLine($"Application thread is thread {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 {Task.CurrentId} on thread {Thread.CurrentThread.ManagedThreadId} is {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函数或通过uloc_getDefault中的函数在类似 Unix 的系统上调用 POSIX setlocale函数,该函数当前使用类别LC_MESSAGES

请注意,如果您设置的特定区域性与系统安装的区域性或用户的首选区域性不同,并且您的应用程序启动多个线程,则这些线程的当前区域性将是函数 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 {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 {Thread.CurrentThread.Name} in application ___domain {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: {CultureInfo.CurrentCulture.Name}");
      Console.WriteLine($"{value:C2}\n");

      Thread.CurrentThread.CurrentCulture = new CultureInfo("fr");
      Console.WriteLine($"Current Culture: {CultureInfo.CurrentCulture.Name}");
      Console.WriteLine($"{value:C2}");
   }
}
// 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设置属性会更改整个应用的区域性;区域性不能按线程设置。