CultureInfo 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
提供有关特定区域性(对于非托管代码开发,则称为“区域设置”)的信息。 这些信息包括区域性的名称、书写系统、使用的日历、字符串的排序顺序以及对日期和数字的格式化设置。
public ref class CultureInfo : IFormatProvider
public ref class CultureInfo : ICloneable, IFormatProvider
public class CultureInfo : IFormatProvider
public class CultureInfo : ICloneable, IFormatProvider
[System.Serializable]
public class CultureInfo : ICloneable, IFormatProvider
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class CultureInfo : ICloneable, IFormatProvider
type CultureInfo = class
interface IFormatProvider
type CultureInfo = class
interface ICloneable
interface IFormatProvider
[<System.Serializable>]
type CultureInfo = class
interface ICloneable
interface IFormatProvider
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type CultureInfo = class
interface ICloneable
interface IFormatProvider
Public Class CultureInfo
Implements IFormatProvider
Public Class CultureInfo
Implements ICloneable, IFormatProvider
- 继承
-
CultureInfo
- 属性
- 实现
示例
以下示例演示如何使用国际排序为西班牙 (西班牙) 创建一个 CultureInfo 对象,并使用传统排序创建另一个 CultureInfo 对象。
using namespace System;
using namespace System::Collections;
using namespace System::Globalization;
int main()
{
// Creates and initializes the CultureInfo which uses the international sort.
CultureInfo^ myCIintl = gcnew CultureInfo( "es-ES",false );
// Creates and initializes the CultureInfo which uses the traditional sort.
CultureInfo^ myCItrad = gcnew CultureInfo( 0x040A,false );
// Displays the properties of each culture.
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "PROPERTY", "INTERNATIONAL", "TRADITIONAL" );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "CompareInfo", myCIintl->CompareInfo, myCItrad->CompareInfo );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "DisplayName", myCIintl->DisplayName, myCItrad->DisplayName );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "EnglishName", myCIintl->EnglishName, myCItrad->EnglishName );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "IsNeutralCulture", myCIintl->IsNeutralCulture, myCItrad->IsNeutralCulture );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "IsReadOnly", myCIintl->IsReadOnly, myCItrad->IsReadOnly );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "LCID", myCIintl->LCID, myCItrad->LCID );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "Name", myCIintl->Name, myCItrad->Name );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "NativeName", myCIintl->NativeName, myCItrad->NativeName );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "Parent", myCIintl->Parent, myCItrad->Parent );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "TextInfo", myCIintl->TextInfo, myCItrad->TextInfo );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "ThreeLetterISOLanguageName", myCIintl->ThreeLetterISOLanguageName, myCItrad->ThreeLetterISOLanguageName );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "ThreeLetterWindowsLanguageName", myCIintl->ThreeLetterWindowsLanguageName, myCItrad->ThreeLetterWindowsLanguageName );
Console::WriteLine( "{0,-31}{1,-47}{2,-25}", "TwoLetterISOLanguageName", myCIintl->TwoLetterISOLanguageName, myCItrad->TwoLetterISOLanguageName );
Console::WriteLine();
// Compare two strings using myCIintl ->
Console::WriteLine( "Comparing \"llegar\" and \"lugar\"" );
Console::WriteLine( " With myCIintl -> CompareInfo -> Compare: {0}", myCIintl->CompareInfo->Compare( "llegar", "lugar" ) );
Console::WriteLine( " With myCItrad -> CompareInfo -> Compare: {0}", myCItrad->CompareInfo->Compare( "llegar", "lugar" ) );
}
/*
This code produces the following output.
PROPERTY INTERNATIONAL TRADITIONAL
CompareInfo CompareInfo - es-ES CompareInfo - es-ES_tradnl
DisplayName Spanish (Spain) Spanish (Spain)
EnglishName Spanish (Spain, International Sort) Spanish (Spain, Traditional Sort)
IsNeutralCulture False False
IsReadOnly False False
LCID 3082 1034
Name es-ES es-ES
NativeName Español (España, alfabetización internacional) Español (España, alfabetización tradicional)
Parent es es
TextInfo TextInfo - es-ES TextInfo - es-ES_tradnl
ThreeLetterISOLanguageName spa spa
ThreeLetterWindowsLanguageName ESN ESP
TwoLetterISOLanguageName es es
Comparing "llegar" and "lugar"
With myCIintl -> CompareInfo -> Compare: -1
With myCItrad -> CompareInfo -> Compare: 1
*/
using System;
using System.Collections;
using System.Globalization;
public class SamplesCultureInfo
{
public static void Main()
{
// Creates and initializes the CultureInfo which uses the international sort.
CultureInfo myCIintl = new CultureInfo("es-ES", false);
// Creates and initializes the CultureInfo which uses the traditional sort.
CultureInfo myCItrad = new CultureInfo(0x040A, false);
// Displays the properties of each culture.
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "PROPERTY", "INTERNATIONAL", "TRADITIONAL");
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "CompareInfo", myCIintl.CompareInfo, myCItrad.CompareInfo);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "DisplayName", myCIintl.DisplayName, myCItrad.DisplayName);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "EnglishName", myCIintl.EnglishName, myCItrad.EnglishName);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "IsNeutralCulture", myCIintl.IsNeutralCulture, myCItrad.IsNeutralCulture);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "IsReadOnly", myCIintl.IsReadOnly, myCItrad.IsReadOnly);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "LCID", myCIintl.LCID, myCItrad.LCID);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "Name", myCIintl.Name, myCItrad.Name);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "NativeName", myCIintl.NativeName, myCItrad.NativeName);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "Parent", myCIintl.Parent, myCItrad.Parent);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "TextInfo", myCIintl.TextInfo, myCItrad.TextInfo);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "ThreeLetterISOLanguageName", myCIintl.ThreeLetterISOLanguageName, myCItrad.ThreeLetterISOLanguageName);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "ThreeLetterWindowsLanguageName", myCIintl.ThreeLetterWindowsLanguageName, myCItrad.ThreeLetterWindowsLanguageName);
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "TwoLetterISOLanguageName", myCIintl.TwoLetterISOLanguageName, myCItrad.TwoLetterISOLanguageName);
Console.WriteLine();
// Compare two strings using myCIintl.
Console.WriteLine("Comparing \"llegar\" and \"lugar\"");
Console.WriteLine(" With myCIintl.CompareInfo.Compare: {0}", myCIintl.CompareInfo.Compare("llegar", "lugar"));
Console.WriteLine(" With myCItrad.CompareInfo.Compare: {0}", myCItrad.CompareInfo.Compare("llegar", "lugar"));
}
}
/*
This code produces the following output.
PROPERTY INTERNATIONAL TRADITIONAL
CompareInfo CompareInfo - es-ES CompareInfo - es-ES_tradnl
DisplayName Spanish (Spain) Spanish (Spain)
EnglishName Spanish (Spain, International Sort) Spanish (Spain, Traditional Sort)
IsNeutralCulture False False
IsReadOnly False False
LCID 3082 1034
Name es-ES es-ES
NativeName Español (España, alfabetización internacional) Español (España, alfabetización tradicional)
Parent es es
TextInfo TextInfo - es-ES TextInfo - es-ES_tradnl
ThreeLetterISOLanguageName spa spa
ThreeLetterWindowsLanguageName ESN ESP
TwoLetterISOLanguageName es es
Comparing "llegar" and "lugar"
With myCIintl.CompareInfo.Compare: -1
With myCItrad.CompareInfo.Compare: 1
*/
Imports System.Collections
Imports System.Globalization
Module Module1
Public Sub Main()
' Creates and initializes the CultureInfo which uses the international sort.
Dim myCIintl As New CultureInfo("es-ES", False)
' Creates and initializes the CultureInfo which uses the traditional sort.
Dim myCItrad As New CultureInfo(&H40A, False)
' Displays the properties of each culture.
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "PROPERTY", "INTERNATIONAL", "TRADITIONAL")
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "CompareInfo", myCIintl.CompareInfo, myCItrad.CompareInfo)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "DisplayName", myCIintl.DisplayName, myCItrad.DisplayName)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "EnglishName", myCIintl.EnglishName, myCItrad.EnglishName)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "IsNeutralCulture", myCIintl.IsNeutralCulture, myCItrad.IsNeutralCulture)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "IsReadOnly", myCIintl.IsReadOnly, myCItrad.IsReadOnly)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "LCID", myCIintl.LCID, myCItrad.LCID)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "Name", myCIintl.Name, myCItrad.Name)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "NativeName", myCIintl.NativeName, myCItrad.NativeName)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "Parent", myCIintl.Parent, myCItrad.Parent)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "TextInfo", myCIintl.TextInfo, myCItrad.TextInfo)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "ThreeLetterISOLanguageName", myCIintl.ThreeLetterISOLanguageName, myCItrad.ThreeLetterISOLanguageName)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "ThreeLetterWindowsLanguageName", myCIintl.ThreeLetterWindowsLanguageName, myCItrad.ThreeLetterWindowsLanguageName)
Console.WriteLine("{0,-31}{1,-47}{2,-25}", "TwoLetterISOLanguageName", myCIintl.TwoLetterISOLanguageName, myCItrad.TwoLetterISOLanguageName)
Console.WriteLine()
' Compare two strings using myCIintl.
Console.WriteLine("Comparing ""llegar"" and ""lugar""")
Console.WriteLine(" With myCIintl.CompareInfo.Compare: {0}", myCIintl.CompareInfo.Compare("llegar", "lugar"))
Console.WriteLine(" With myCItrad.CompareInfo.Compare: {0}", myCItrad.CompareInfo.Compare("llegar", "lugar"))
End Sub
'This code produces the following output.
'
'PROPERTY INTERNATIONAL TRADITIONAL
'CompareInfo CompareInfo - es-ES CompareInfo - es-ES_tradnl
'DisplayName Spanish (Spain) Spanish (Spain)
'EnglishName Spanish (Spain, International Sort) Spanish (Spain, Traditional Sort)
'IsNeutralCulture False False
'IsReadOnly False False
'LCID 3082 1034
'Name es-ES es-ES
'NativeName Español (España, alfabetización internacional) Español (España, alfabetización tradicional)
'Parent es es
'TextInfo TextInfo - es-ES TextInfo - es-ES_tradnl
'ThreeLetterISOLanguageName spa spa
'ThreeLetterWindowsLanguageName ESN ESP
'TwoLetterISOLanguageName es es
'
'Comparing "llegar" and "lugar"
' With myCIintl.CompareInfo.Compare: -1
' With myCItrad.CompareInfo.Compare: 1
End Module
注解
类 CultureInfo 提供特定于区域性的信息,例如语言、子语言、国家/地区、日历以及与特定区域性关联的约定。 此类还提供对 、NumberFormatInfo、 CompareInfo和 TextInfo 对象的区域性特定实例DateTimeFormatInfo的访问。 这些对象包含特定于区域性的操作所需的信息,例如大小写、设置日期和数字格式以及比较字符串。 类 CultureInfo 直接或间接由格式化、分析或操作区域性特定的数据(如 String、 DateTime、 DateTimeOffset和 数值类型)的类使用。
本节内容:
区域性名称和标识符
固定区域性、非特定区域性和特定区域性
自定义区域性
动态区域性数据
CultureInfo 和文化数据
当前区域性和当前 UI 区域性
获取所有区域性
区域性和线程
区域性和应用程序域
区域性和基于任务的异步操作
CultureInfo 对象序列化
控制面板替代
备用排序顺序
区域性和 Windows 应用
区域性名称和标识符
类 CultureInfo 根据 RFC 4646 为每个区域性指定唯一名称。 该名称是与语言关联的 ISO 639 双字母或三字母小写区域性代码和与国家或地区关联的 ISO 3166 双字母大写子区域性代码的组合。 此外,对于面向 .NET Framework 4 或更高版本且在 Windows 10 或更高版本下运行的应用,支持对应于有效 BCP-47 语言标记的区域性名称。
注意
将区域性名称传递给类构造函数或方法(如 CreateSpecificCulture 或 CultureInfo)时,其大小写并不重要。
基于 RFC 4646 的区域性名称的格式为 languagecode2
-country/regioncode2
,其中 languagecode2
是双字母语言代码, country/regioncode2
是双字母子区域性代码。 示例包括ja-JP
日语 (日本) 和en-US
英语 (美国) 。 如果双字母语言代码不可用,则使用 ISO 639-3 中定义的三字母代码。
某些区域性名称还指定 ISO 15924 脚本。 例如,Cyrl 指定西里尔文脚本,Latn 指定拉丁文脚本。 包含脚本的区域性名称使用模式 languagecode2
country/regioncode2
-scripttag
-。 此类文化名称的一个示例是 uz-Cyrl-UZ
乌兹别克语 (西里尔文,乌兹别克斯坦) 。 在 Windows Vista 之前的 Windows 操作系统上,包含脚本的区域性名称使用 模式languagecode2
--country/regioncode2
scripttag
,例如,uz-UZ-Cyrl
对于乌兹别克语 (西里尔文、乌兹别克斯坦) 。
非特定区域性仅由两个字母的小写语言代码指定。 例如, fr
指定法语的中性区域性,并为 de
德语指定非特定区域性。
注意
有两个区域性名称与此规则相矛盾。 名为 的中文 (简体) 和名为 zh-Hans
的中文 (传统) zh-Hant
是中性区域性。 区域性名称表示当前标准,除非你有使用旧名称和 zh-CHS
zh-CHT
的原因,否则应使用。
区域性标识符是标准的国际数字缩写,具有唯一标识其中一个已安装区域性所需的组件。 应用程序可以使用预定义的区域性标识符或定义自定义标识符。
命名空间中的 System.Globalization 此类和其他类使用某些预定义区域性名称和标识符。 有关 Windows 系统的详细区域性信息,请参阅 Windows 支持的语言/区域名称列表中的“语言标记”列。 列名遵循 BCP 47 定义的标准。
区域性名称和标识符仅表示可在特定计算机上找到的区域性的子集。 Windows 版本或 Service Pack 可以更改可用区域性。 应用程序可以使用 类添加自定义区域性 CultureAndRegionInfoBuilder 。 用户可以使用 Microsoft 区域设置生成器 工具添加自己的自定义区域性。 Microsoft Locale Builder 使用 CultureAndRegionInfoBuilder
类以托管代码编写。
多个非重复名称与区域性密切相关,尤其是与以下类成员关联的名称:
固定区域性、非特定区域性和特定区域性
区域性通常分为三组:固定区域性、中性区域性和特定区域性。
固定区域性不区分区域性。 应用程序使用空字符串 (“”) 或其标识符按名称指定固定区域性。 InvariantCulture 定义固定区域性的实例。 它与英语相关联,但不与任何国家/地区相关联。 它几乎用于命名空间中 Globalization
需要区域性的任何方法。
非特定区域性是一种与语言(而不是国家/地区)关联的区域性。 特定区域性是与语言和国家/地区关联的区域性。 例如, fr
是法国区域性的中性名称,是 fr-FR
特定法语 (法国) 区域性的名称。 请注意,中文 (简体) 和中文 (传统) 也被视为中性文化。
不建议为非特定区域性创建类的实例 CompareInfo ,因为它包含的数据是任意的。 若要显示和排序数据,请同时指定语言和区域。 此外, Name 为非特定区域性创建的 对象的 属性 CompareInfo 仅返回国家/地区,不包括区域。
定义的区域性具有层次结构,其中特定区域性的父区域性为中性区域性,而非特定区域性的父区域性为固定区域性。 属性 Parent 包含与特定区域性关联的非特定区域性。 自定义区域性应根据此模式定义 Parent 属性。
如果特定区域性的资源在操作系统中不可用,则使用关联非特定区域性的资源。 如果非特定区域性的资源不可用,则使用嵌入在main程序集中的资源。 有关资源回退过程的详细信息,请参阅 打包和部署资源。
Windows API 中的区域设置列表与 .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 Framework 3.5 及更早版本中,区域性数据由 Windows 操作系统和.NET Framework提供。
在 .NET Framework 4 及更高版本中,区域性数据由 Windows 操作系统提供。
在 Windows 上运行的所有 .NET Core 版本中,区域性数据由 Windows 操作系统提供。
在 Unix 平台上运行的所有 .NET Core 版本中,区域性数据由 Unicode 国际组件 (ICU) 库提供。 ICU 库的特定版本取决于各个操作系统。
因此,特定 .NET 实现、平台或版本上可用的区域性可能不适用于其他 .NET 实现、平台或版本。
某些 CultureInfo
对象因基础平台而异。 具体而言, zh-CN
、 或中文 (简体、中国) 和 zh-TW
(或中文 (繁体中文、台湾) )是 Windows 系统上的可用区域性,但它们是 Unix 系统上的别名区域性。 “zh-CN”是“zh-Hans-CN”区域性的别名,“zh-TW”是“zh-Hant-TW”区域性的别名。 别名区域性不会由对 GetCultures 方法的调用返回,并且可能具有与 Windows 对应项不同的属性值,包括不同的 Parent 区域性。 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 系统上,在表示“zh-CN”区域性的实例上调用 CultureInfo.Equals ,并向其传递“zh-Hans-CN”实例将
true
返回 。 在 Unix 系统上,方法调用返回false
。 此行为也适用于在“zh-TW”CultureInfo实例上调用Equals并向其传递“zh-Hant-Tw”实例。
动态区域性数据
除固定区域性外,区域性数据是动态的。 即使对于预定义区域性也是如此。 例如,国家或地区采用新货币、更改字词拼写或更改首选日历,区域性定义更改以跟踪此情况。 自定义区域性可能会更改,无需通知,任何特定区域性都可能被自定义替换区域性覆盖。 此外,如下所述,单个用户可以替代文化首选项。 应用程序应始终在运行时获取区域性数据。
注意
保存数据时,应用程序应使用固定区域性、二进制格式或与区域性无关的特定格式。 根据与特定区域性(非固定区域性)关联的当前值保存的数据可能会变得不可读,或者如果该区域性发生更改,其含义可能会发生变化。
当前区域性和当前 UI 区域性
.NET 应用程序中的每个线程都有当前区域性和当前 UI 区域性。 当前区域性确定日期、时间、数字和货币值的格式设置约定、文本排序顺序、大小写约定以及字符串的比较方式。 当前 UI 区域性用于在运行时检索特定于区域性的资源。
注意
有关如何按线程确定当前和当前 UI 区域性的信息,请参阅 区域性和线程 部分。 有关如何在新应用程序域中执行的线程以及跨应用程序域边界的线程上确定当前和当前 UI 区域性的信息,请参阅 区域性和应用程序域 部分。 有关如何在执行基于任务的异步操作的线程上确定当前和当前 UI 区域性的信息,请参阅 区域性和基于任务的异步操作 部分。
有关当前区域性的更多详细信息,请参阅 CultureInfo.CurrentCulture 属性主题。 有关当前 UI 区域性的更多详细信息,请参阅 CultureInfo.CurrentUICulture 属性主题。
检索当前和当前 UI 区域性
可以通过以下两种方式之一 CultureInfo 获取表示当前区域性的 对象:
通过检索 属性的值 CultureInfo.CurrentCulture 。
通过检索 Thread.CurrentThread.CurrentCulture 属性的值。
以下示例检索这两个属性值,比较它们以显示它们相等,并显示当前区域性的名称。
using System;
using System.Globalization;
using System.Threading;
public class Example
{
public static void Main()
{
CultureInfo culture1 = CultureInfo.CurrentCulture;
CultureInfo culture2 = Thread.CurrentThread.CurrentCulture;
Console.WriteLine("The current culture is {0}", culture1.Name);
Console.WriteLine("The two CultureInfo objects are equal: {0}",
culture1 == culture2);
}
}
// The example displays output like the following:
// The current culture is en-US
// The two CultureInfo objects are equal: True
Imports System.Globalization
Imports System.Threading
Module Example
Public Sub Main()
Dim culture1 As CultureInfo = CultureInfo.CurrentCulture
Dim culture2 As CultureInfo = Thread.CurrentThread.CurrentCulture
Console.WriteLine("The current culture is {0}", culture1.Name)
Console.WriteLine("The two CultureInfo objects are equal: {0}",
culture1.Equals(culture2))
End Sub
End Module
' The example displays output like the following:
' The current culture is en-US
' The two CultureInfo objects are equal: True
可以通过以下两种方式之一 CultureInfo 获取表示当前 UI 区域性的对象:
通过检索 属性的值 CultureInfo.CurrentUICulture 。
通过检索 Thread.CurrentThread.CurrentUICulture 属性的值。
以下示例检索这两个属性值,比较它们以显示它们相等,并显示当前 UI 区域性的名称。
using System;
using System.Globalization;
using System.Threading;
public class Example
{
public static void Main()
{
CultureInfo uiCulture1 = CultureInfo.CurrentUICulture;
CultureInfo uiCulture2 = Thread.CurrentThread.CurrentUICulture;
Console.WriteLine("The current UI culture is {0}", uiCulture1.Name);
Console.WriteLine("The two CultureInfo objects are equal: {0}",
uiCulture1 == uiCulture2);
}
}
// The example displays output like the following:
// The current UI culture is en-US
// The two CultureInfo objects are equal: True
Imports System.Globalization
Imports System.Threading
Module Example
Public Sub Main()
Dim uiCulture1 As CultureInfo = CultureInfo.CurrentUICulture
Dim uiCulture2 As CultureInfo = Thread.CurrentThread.CurrentUICulture
Console.WriteLine("The current UI culture is {0}", uiCulture1.Name)
Console.WriteLine("The two CultureInfo objects are equal: {0}",
uiCulture1.Equals(uiCulture2))
End Sub
End Module
' The example displays output like the following:
' The current UI culture is en-US
' The two CultureInfo objects are equal: True
设置当前和当前 UI 区域性
若要更改线程的区域性和 UI 区域性,请执行以下操作:
通过调用CultureInfo类构造函数并向其传递区域性的名称来实例化CultureInfo表示该区域性的 对象。 如果新区域性与当前 Windows 区域性相同,则 CultureInfo(String) 构造函数实例化一个 CultureInfo 对象,该对象反映用户重写。 构造 CultureInfo(String, Boolean) 函数允许指定新实例化 CultureInfo 的对象是否反映用户重写(如果新区域性与当前 Windows 区域性相同)。
将 CultureInfo 对象分配给 CultureInfo.CurrentCulture .NET Core 和 .NET Framework 4.6 及更高版本的 或 CultureInfo.CurrentUICulture 属性。 (在 .NET Framework 4.5.2 及更早版本上,可以将 对象分配给
CultureInfo
Thread.CurrentCulture 或 Thread.CurrentUICulture property.)
以下示例检索当前区域性。 如果不是法国 (法国) 文化,它将当前文化更改为法国 (法国) 。 否则,它将当前文化更改为法国 (卢森堡) 。
using System;
using System.Globalization;
public class Example
{
public static void Main()
{
CultureInfo current = CultureInfo.CurrentCulture;
Console.WriteLine("The current culture is {0}", 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 {0}",
CultureInfo.CurrentCulture.Name);
}
}
// The example displays output like the following:
// The current culture is en-US
// The current culture is now fr-FR
Imports System.Globalization
Module Example
Public Sub Main()
Dim current As CultureInfo = CultureInfo.CurrentCulture
Console.WriteLine("The current culture is {0}", current.Name)
Dim newCulture As CultureInfo
If current.Name.Equals("fr-FR") Then
newCulture = New CultureInfo("fr-LU")
Else
newCulture = new CultureInfo("fr-FR")
End If
CultureInfo.CurrentCulture = newCulture
Console.WriteLine("The current culture is now {0}",
CultureInfo.CurrentCulture.Name)
End Sub
End Module
' 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 Example
{
public static void Main()
{
CultureInfo current = CultureInfo.CurrentUICulture;
Console.WriteLine("The current UI culture is {0}", 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 {0}",
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
Imports System.Globalization
Module Example
Public Sub Main()
Dim current As CultureInfo = CultureInfo.CurrentUICulture
Console.WriteLine("The current UI culture is {0}", current.Name)
Dim newUICulture As CultureInfo
If current.Name.Equals("sl-SI") Then
newUICulture = New CultureInfo("hr-HR")
Else
newUICulture = new CultureInfo("sl-SI")
End If
CultureInfo.CurrentUICulture = newUICulture
Console.WriteLine("The current UI culture is now {0}",
CultureInfo.CurrentUICulture.Name)
End Sub
End Module
' 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 Example
{
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(" {0} -- {1}", 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(" {0} -- {1}", 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.
Imports System.Globalization
Module Example
Public Sub Main()
' Get all custom cultures.
Dim custom() As CultureInfo = CultureInfo.GetCultures(CultureTypes.UserCustomCulture)
If custom.Length = 0 Then
Console.WriteLine("There are no user-defined custom cultures.")
Else
Console.WriteLine("Custom cultures:")
For Each culture In custom
Console.WriteLine(" {0} -- {1}", culture.Name, culture.DisplayName)
Next
End If
Console.WriteLine()
' Get all replacement cultures.
Dim replacements() As CultureInfo = CultureInfo.GetCultures(CultureTypes.ReplacementCultures)
If replacements.Length = 0 Then
Console.WriteLine("There are no replacement cultures.")
Else
Console.WriteLine("Replacement cultures:")
For Each culture in replacements
Console.WriteLine(" {0} -- {1}", culture.Name, culture.DisplayName)
Next
End If
Console.WriteLine()
End Sub
End Module
' 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.
区域性和线程
启动新的应用程序线程时,其当前区域性和当前 UI 区域性由当前系统区域性(而不是当前线程区域性)定义。 以下示例演示了差异。 它将应用程序线程的当前区域性和当前 UI 区域性设置为法国 (法国) 区域性 (fr-FR) 。 如果当前区域性已是 fr-FR,则本示例将其设置为英语 (美国) 区域性 (en-US) 。 它将三个随机数显示为货币值,然后创建一个新线程,该线程又将三个随机数显示为货币值。 但如示例输出所示,新线程显示的货币值并不反映法国 (法国) 区域性的格式设置约定,这与main应用程序线程的输出不同。
using System;
using System.Globalization;
using System.Threading;
public class Example
{
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: '{0}'",
Thread.CurrentThread.Name);
Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
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(" {0:C2}", rnd.NextDouble() * 10);
}
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
Imports System.Globalization
Imports System.Threading
Module Example
Dim rnd As New Random()
Public Sub Main()
If Thread.CurrentThread.CurrentCulture.Name <> "fr-FR" Then
' 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")
End If
ThreadProc()
Dim worker As New Thread(AddressOf ThreadProc)
worker.Name = "WorkerThread"
worker.Start()
End Sub
Private Sub DisplayThreadInfo()
Console.WriteLine()
Console.WriteLine("Current Thread Name: '{0}'",
Thread.CurrentThread.Name)
Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
Thread.CurrentThread.CurrentCulture.Name,
Thread.CurrentThread.CurrentUICulture.Name)
End Sub
Private Sub DisplayValues()
' Create new thread and display three random numbers.
Console.WriteLine("Some currency values:")
For ctr As Integer = 0 To 3
Console.WriteLine(" {0:C2}", rnd.NextDouble() * 10)
Next
End Sub
Private Sub ThreadProc()
DisplayThreadInfo()
DisplayValues()
End Sub
End Module
' 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
在 .NET Framework 4.5 之前的 .NET Framework 版本中,确保main应用程序线程与所有其他工作线程共享同一CultureInfo区域性的最常用方法是将应用程序范围的区域性的名称或表示应用程序范围的区域性的对象传递给System.Threading.ParameterizedThreadStart委托。 以下示例使用此方法来确保两个线程显示的货币值反映同一区域性的格式设置约定。
using System;
using System.Globalization;
using System.Threading;
public class Example
{
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");
}
DisplayThreadInfo();
DisplayValues();
Thread worker = new Thread(Example.ThreadProc);
worker.Name = "WorkerThread";
worker.Start(Thread.CurrentThread.CurrentCulture);
}
private static void DisplayThreadInfo()
{
Console.WriteLine("\nCurrent Thread Name: '{0}'",
Thread.CurrentThread.Name);
Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
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(" {0:C2}", rnd.NextDouble() * 10);
}
private static void ThreadProc(Object obj)
{
Thread.CurrentThread.CurrentCulture = (CultureInfo) obj;
Thread.CurrentThread.CurrentUICulture = (CultureInfo) obj;
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 €
Imports System.Globalization
Imports System.Threading
Module Example
Dim rnd As New Random()
Public Sub Main()
If Thread.CurrentThread.CurrentCulture.Name <> "fr-FR" Then
' 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")
End If
DisplayThreadInfo()
DisplayValues()
Dim worker As New Thread(AddressOf ThreadProc)
worker.Name = "WorkerThread"
worker.Start(Thread.CurrentThread.CurrentCulture)
End Sub
Private Sub DisplayThreadInfo()
Console.WriteLine()
Console.WriteLine("Current Thread Name: '{0}'",
Thread.CurrentThread.Name)
Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
Thread.CurrentThread.CurrentCulture.Name,
Thread.CurrentThread.CurrentUICulture.Name)
End Sub
Private Sub DisplayValues()
' Create new thread and display three random numbers.
Console.WriteLine("Some currency values:")
For ctr As Integer = 0 To 3
Console.WriteLine(" {0:C2}", rnd.NextDouble() * 10)
Next
End Sub
Private Sub ThreadProc(obj As Object)
Thread.CurrentThread.CurrentCulture = CType(obj, CultureInfo)
Thread.CurrentThread.CurrentUICulture = CType(obj, CultureInfo)
DisplayThreadInfo()
DisplayValues()
End Sub
End Module
' 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 €
可以通过调用 ThreadPool.QueueUserWorkItem(WaitCallback, Object) 方法,以类似的方式设置线程池线程的区域性和 UI 区域性。
从 .NET Framework 4.5 开始,可以通过将表示该区域性的对象分配给 CultureInfo 和 属性,更直接地设置应用程序域中所有线程的区域性和 DefaultThreadCurrentUICulture UI 区域性DefaultThreadCurrentCulture。 以下示例使用这些属性来确保默认应用程序域中的所有线程共享相同的区域性。
using System;
using System.Globalization;
using System.Threading;
public class Example
{
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(Example.ThreadProc);
worker.Name = "WorkerThread";
worker.Start();
}
private static void DisplayThreadInfo()
{
Console.WriteLine("\nCurrent Thread Name: '{0}'",
Thread.CurrentThread.Name);
Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
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(" {0:C2}", rnd.NextDouble() * 10);
}
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 €
Imports System.Globalization
Imports System.Threading
Module Example
Dim rnd As New Random()
Public Sub Main()
If Thread.CurrentThread.CurrentCulture.Name <> "fr-FR" Then
' 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")
End If
ThreadProc()
Dim worker As New Thread(AddressOf ThreadProc)
worker.Name = "WorkerThread"
worker.Start()
End Sub
Private Sub DisplayThreadInfo()
Console.WriteLine()
Console.WriteLine("Current Thread Name: '{0}'",
Thread.CurrentThread.Name)
Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
Thread.CurrentThread.CurrentCulture.Name,
Thread.CurrentThread.CurrentUICulture.Name)
End Sub
Private Sub DisplayValues()
' Create new thread and display three random numbers.
Console.WriteLine("Some currency values:")
For ctr As Integer = 0 To 3
Console.WriteLine(" {0:C2}", rnd.NextDouble() * 10)
Next
End Sub
Private Sub ThreadProc()
DisplayThreadInfo()
DisplayValues()
End Sub
End Module
' 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 属性是静态成员,但它们仅为设置这些属性值时当前的应用程序域定义默认区域性和默认 UI 区域性。 有关详细信息,请参阅下一部分 区域性和应用程序域。
向 和 DefaultThreadCurrentUICulture 属性赋值DefaultThreadCurrentCulture时,如果未显式为线程分配区域性,则应用程序域中线程的区域性和 UI 区域性也会更改。 但是,这些线程仅在当前应用程序域中执行时反映新的区域性设置。 如果这些线程在另一个应用程序域中执行,则它们的区域性将成为为该应用程序域定义的默认区域性。 因此,建议始终设置main应用程序线程的区域性,而不是依赖 DefaultThreadCurrentCulture 和 DefaultThreadCurrentUICulture 属性来更改它。
区域性和应用程序域
DefaultThreadCurrentCulture 和 DefaultThreadCurrentUICulture 是静态属性,仅在设置或检索属性值时显式定义应用程序域的默认区域性。 以下示例将默认应用程序域中的默认区域性和默认 UI 区域性设置为 French (France) ,然后使用 AppDomainSetup 类和 AppDomainInitializer 委托将新应用程序域中的默认区域性和 UI 区域性设置为俄语 (俄罗斯) 。 然后,单个线程在每个应用程序域中执行两种方法。 请注意,线程的区域性和 UI 区域性未显式设置;它们派生自执行线程的应用程序域的默认区域性和 UI 区域性。 另请注意, DefaultThreadCurrentCulture 和 DefaultThreadCurrentUICulture 属性返回应用程序域的默认值 CultureInfo ,在进行方法调用时是当前的。
using System;
using System.Globalization;
using System.Reflection;
using System.Threading;
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 {0:D}", DateTime.Now);
}
public void DisplayCultures()
{
Console.WriteLine("Application domain is {0}", AppDomain.CurrentDomain.Id);
Console.WriteLine("Default Culture: {0}", CultureInfo.DefaultThreadCurrentCulture);
Console.WriteLine("Default UI Culture: {0}", 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
Imports System.Globalization
Imports System.Reflection
Imports System.Threading
Module Example
Public Sub Main()
' Set the default culture and display the current date in the current application domain.
Dim info1 As New Info()
SetAppDomainCultures("fr-FR")
' Create a second application domain.
Dim setup As New AppDomainSetup()
setup.AppDomainInitializer = AddressOf SetAppDomainCultures
setup.AppDomainInitializerArguments = { "ru-RU" }
Dim domain As AppDomain = AppDomain.CreateDomain("Domain2", Nothing, setup)
' Create an Info object in the new application domain.
Dim info2 As Info = CType(domain.CreateInstanceAndUnwrap(GetType(Example).Assembly.FullName,
"Info"), Info)
' Execute methods in the two application domains.
info2.DisplayDate()
info2.DisplayCultures()
info1.DisplayDate()
info1.DisplayCultures()
End Sub
Public Sub SetAppDomainCultures(names() As String)
SetAppDomainCultures(names(0))
End Sub
Public Sub SetAppDomainCultures(name As String)
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 e As CultureNotFoundException
Return
Catch e As ArgumentException
Return
End Try
End Sub
End Module
Public Class Info : Inherits MarshalByRefObject
Public Sub DisplayDate()
Console.WriteLine("Today is {0:D}", Date.Now)
End Sub
Public Sub DisplayCultures()
Console.WriteLine("Application domain is {0}", AppDomain.CurrentDomain.Id)
Console.WriteLine("Default Culture: {0}", CultureInfo.DefaultThreadCurrentCulture)
Console.WriteLine("Default UI Culture: {0}", CultureInfo.DefaultThreadCurrentUICulture)
End Sub
End Class
' 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 或更高版本的应用,区域性是异步操作上下文的一部分。 换句话说,从面向 .NET Framework 4.6 的应用开始,异步操作默认继承启动它们的线程的 和 CurrentUICulture 属性的值CurrentCulture。 如果当前区域性或当前 UI 区域性不同于系统区域性,则当前区域性会跨越线程边界,成为正在执行异步操作的线程池线程的当前区域性。
下面的示例提供了简单的演示。 它使用 TargetFrameworkAttribute 特性来面向 4.6 .NET Framework。 该示例定义了一个 Func<TResult> 委托 , formatDelegate
该委托返回一些格式为货币值的数字。 该示例将当前系统区域性更改为法语 (法国) ,或者,如果法语 (法国) 已是当前区域性,则英语 (美国) 。 然后:
直接调用委托,使其在main应用线程上同步运行。
创建一个任务,该任务在线程池线程上异步执行委托。
创建一个任务,该任务通过调用 Task.RunSynchronously 方法在main应用线程上同步执行委托。
如示例输出所示,当当前区域性更改为法语 (法国) 时,异步调用任务的线程的当前区域性将成为该异步操作的当前区域性。
using System;
using System.Globalization;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
[assembly:TargetFramework(".NETFramework,Version=v4.6")]
public class Example
{
public static void Main()
{
decimal[] values = { 163025412.32m, 18905365.59m };
string formatString = "C2";
Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId);
foreach (var value in values)
output += String.Format("{0} ", value.ToString(formatString));
output += Environment.NewLine;
return output;
};
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
// Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
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 {0}.\n",
CultureInfo.CurrentCulture.Name);
// 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 €
Imports System.Globalization
Imports System.Runtime.Versioning
Imports System.Threading
Imports System.Threading.Tasks
<Assembly:TargetFramework(".NETFramework,Version=v4.6")>
Module Example
Public Sub Main()
Dim values() As Decimal = { 163025412.32d, 18905365.59d }
Dim formatString As String = "C2"
Dim formatDelegate As Func(Of String) = Function()
Dim output As String = String.Format("Formatting using the {0} culture on thread {1}.",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId)
output += Environment.NewLine
For Each value In values
output += String.Format("{0} ", value.ToString(formatString))
Next
output += Environment.NewLine
Return output
End Function
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId)
' Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
CultureInfo.CurrentCulture.Name)
If CultureInfo.CurrentCulture.Name = "fr-FR" Then
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Else
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR")
End If
Console.WriteLine("Changed the current culture to {0}.",
CultureInfo.CurrentCulture.Name)
Console.WriteLine()
' 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:")
Dim t1 = Task.Run(formatDelegate)
Console.WriteLine(t1.Result)
Console.WriteLine("Executing a task synchronously:")
Dim t2 = New Task(Of String)(formatDelegate)
t2.RunSynchronously()
Console.WriteLine(t2.Result)
End Sub
End Module
' 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 Imports the fr-FR culture on thread 1.
' 163 025 412,32 € 18 905 365,59 €
'
' Executing a task asynchronously:
' Formatting Imports the fr-FR culture on thread 3.
' 163 025 412,32 € 18 905 365,59 €
'
' Executing a task synchronously:
' Formatting Imports the fr-FR culture on thread 1.
' 163 025 412,32 € 18 905 365,59 €
对于面向 .NET Framework 4.6 之前的 .NET Framework 版本的应用,或者对于不面向特定版本的 .NET Framework 的应用,调用线程的区域性不是任务上下文的一部分。 相反,除非显式定义一个线程,否则新线程的区域性默认为系统区域性。 以下示例与上一个示例相同,只不过它缺少 TargetFrameworkAttribute 属性, 对此进行了说明。 由于执行该示例的系统的系统区域性是英语 (美国) ,因此在线程池线程上异步执行的任务的区域性不是 en-US
fr-FR
。
using System;
using System.Globalization;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
decimal[] values = { 163025412.32m, 18905365.59m };
string formatString = "C2";
Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId);
foreach (var value in values)
output += String.Format("{0} ", value.ToString(formatString));
output += Environment.NewLine;
return output;
};
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
// Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
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 {0}.\n",
CultureInfo.CurrentCulture.Name);
// 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 en-US 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 €
Imports System.Globalization
Imports System.Runtime.Versioning
Imports System.Threading
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim values() As Decimal = { 163025412.32d, 18905365.59d }
Dim formatString As String = "C2"
Dim formatDelegate As Func(Of String) = Function()
Dim output As String = String.Format("Formatting using the {0} culture on thread {1}.",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId)
output += Environment.NewLine
For Each value In values
output += String.Format("{0} ", value.ToString(formatString))
Next
output += Environment.NewLine
Return output
End Function
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId)
' Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
CultureInfo.CurrentCulture.Name)
If CultureInfo.CurrentCulture.Name = "fr-FR" Then
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Else
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR")
End If
Console.WriteLine("Changed the current culture to {0}.",
CultureInfo.CurrentCulture.Name)
Console.WriteLine()
' 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:")
Dim t1 = Task.Run(formatDelegate)
Console.WriteLine(t1.Result)
Console.WriteLine("Executing a task synchronously:")
Dim t2 = New Task(Of String)(formatDelegate)
t2.RunSynchronously()
Console.WriteLine(t2.Result)
End Sub
End Module
' 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 en-US 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 €
对于面向 .NET Framework 4.5 及更高版本但低于 .NET Framework 4.6 的 .NET Framework 版本的应用,可以使用 DefaultThreadCurrentCulture 和 DefaultThreadCurrentUICulture 属性来确保在线程池线程上执行的异步任务中使用调用线程的区域性。 以下示例与上一个示例相同,只不过它使用 DefaultThreadCurrentCulture 属性来确保线程池线程具有与main应用线程相同的区域性。
using System;
using System.Globalization;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
decimal[] values = { 163025412.32m, 18905365.59m };
string formatString = "C2";
Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId);
foreach (var value in values)
output += String.Format("{0} ", value.ToString(formatString));
output += Environment.NewLine;
return output;
};
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
// Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
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 {0}.\n",
CultureInfo.CurrentCulture.Name);
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture;
// 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 €
Imports System.Globalization
Imports System.Runtime.Versioning
Imports System.Threading
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim values() As Decimal = { 163025412.32d, 18905365.59d }
Dim formatString As String = "C2"
Dim formatDelegate As Func(Of String) = Function()
Dim output As String = String.Format("Formatting using the {0} culture on thread {1}.",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId)
output += Environment.NewLine
For Each value In values
output += String.Format("{0} ", value.ToString(formatString))
Next
output += Environment.NewLine
Return output
End Function
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId)
' Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
CultureInfo.CurrentCulture.Name)
If CultureInfo.CurrentCulture.Name = "fr-FR" Then
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Else
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR")
End If
Console.WriteLine("Changed the current culture to {0}.",
CultureInfo.CurrentCulture.Name)
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture
Console.WriteLine()
' 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:")
Dim t1 = Task.Run(formatDelegate)
Console.WriteLine(t1.Result)
Console.WriteLine("Executing a task synchronously:")
Dim t2 = New Task(Of String)(formatDelegate)
t2.RunSynchronously()
Console.WriteLine(t2.Result)
End Sub
End Module
' 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 或更高版本的应用,即使任务跨越应用域边界,调用线程的区域性仍属于异步任务的上下文。
以下示例表明,即使任务正在执行的方法跨越应用程序域边界,调用线程的区域性仍保留基于任务的异步操作的当前区域性。 它定义了一个类, DataRetriever
使用单个方法 GetFormattedNumber
,该类返回一个随机双精度浮点数,介于 1 到 1,000 之间,格式为货币值。 运行第一个任务,只需实例化 DataRetriever
实例并调用其 GetFormattedNumber
方法。 第二个任务报告其当前应用程序域,创建新的应用程序域,实例化 DataRetriever
新应用程序域中的实例,并调用其 GetFormattedNumber
方法。 如示例输出所示,当调用线程、第一个任务和第二个任务在main应用程序域和第二个应用程序域中执行时,当前区域性保持不变。
using System;
using System.Globalization;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
[assembly:TargetFramework(".NETFramework,Version=v4.6")]
public class Example
{
public static void Main()
{
string formatString = "C2";
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
// Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
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 {0}.\n",
CultureInfo.CurrentCulture.Name);
// Call an async delegate to format the values using one format string.
Console.WriteLine("Executing a task asynchronously in the main appdomain:");
var t1 = Task.Run(() => { DataRetriever d = new DataRetriever();
return d.GetFormattedNumber(formatString);
});
Console.WriteLine(t1.Result);
Console.WriteLine();
Console.WriteLine("Executing a task synchronously in two appdomains:");
var t2 = Task.Run(() => { Console.WriteLine("Thread {0} is running in app domain '{1}'",
Thread.CurrentThread.ManagedThreadId,
AppDomain.CurrentDomain.FriendlyName);
AppDomain domain = AppDomain.CreateDomain("Domain2");
DataRetriever d = (DataRetriever) domain.CreateInstanceAndUnwrap(typeof(Example).Assembly.FullName,
"DataRetriever");
return d.GetFormattedNumber(formatString);
});
Console.WriteLine(t2.Result);
}
}
public class DataRetriever : MarshalByRefObject
{
public string GetFormattedNumber(String format)
{
Thread thread = Thread.CurrentThread;
Console.WriteLine("Current culture is {0}", thread.CurrentCulture);
Console.WriteLine("Thread {0} is running in app domain '{1}'",
thread.ManagedThreadId,
AppDomain.CurrentDomain.FriendlyName);
Random rnd = new Random();
Double value = rnd.NextDouble() * 1000;
return value.ToString(format);
}
}
// The example displays output like the following:
// The example is running on thread 1
// The current culture is en-US
// Changed the current culture to fr-FR.
//
// Executing a task asynchronously in a single appdomain:
// Current culture is fr-FR
// Thread 3 is running in app domain 'AsyncCulture4.exe'
// 93,48 €
//
// Executing a task synchronously in two appdomains:
// Thread 4 is running in app domain 'AsyncCulture4.exe'
// Current culture is fr-FR
// Thread 4 is running in app domain 'Domain2'
// 288,66 €
Imports System.Globalization
Imports System.Runtime.Versioning
Imports System.Threading
Imports System.Threading.Tasks
<Assembly:TargetFramework(".NETFramework,Version=v4.6")>
Module Example
Public Sub Main()
Dim formatString As String = "C2"
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId)
' Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
CultureInfo.CurrentCulture.Name)
If CultureInfo.CurrentCulture.Name = "fr-FR" Then
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Else
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR")
End If
Console.WriteLine("Changed the current culture to {0}.",
CultureInfo.CurrentCulture.Name)
Console.WriteLine()
' Call an async delegate to format the values using one format string.
Console.WriteLine("Executing a task asynchronously in the main appdomain:")
Dim t1 = Task.Run(Function()
Dim d As New DataRetriever()
Return d.GetFormattedNumber(formatString)
End Function)
Console.WriteLine(t1.Result)
Console.WriteLine()
Console.WriteLine("Executing a task synchronously in two appdomains:")
Dim t2 = Task.Run(Function()
Console.WriteLine("Thread {0} is running in app domain '{1}'",
Thread.CurrentThread.ManagedThreadId,
AppDomain.CurrentDomain.FriendlyName)
Dim domain As AppDomain = AppDomain.CreateDomain("Domain2")
Dim d As DataRetriever = CType(domain.CreateInstanceAndUnwrap(GetType(Example).Assembly.FullName,
"DataRetriever"), DataRetriever)
Return d.GetFormattedNumber(formatString)
End Function)
Console.WriteLine(t2.Result)
End Sub
End Module
Public Class DataRetriever : Inherits MarshalByRefObject
Public Function GetFormattedNumber(format As String) As String
Dim thread As Thread = Thread.CurrentThread
Console.WriteLine("Current culture is {0}", thread.CurrentCulture)
Console.WriteLine("Thread {0} is running in app domain '{1}'",
thread.ManagedThreadId,
AppDomain.CurrentDomain.FriendlyName)
Dim rnd As New Random()
Dim value As Double = rnd.NextDouble() * 1000
Return value.ToString(format)
End Function
End Class
' The example displays output like the following:
' The example is running on thread 1
' The current culture is en-US
' Changed the current culture to fr-FR.
'
' Executing a task asynchronously in a single appdomain:
' Current culture is fr-FR
' Thread 3 is running in app domain 'AsyncCulture4.exe'
' 93,48 €
'
' Executing a task synchronously in two appdomains:
' Thread 4 is running in app domain 'AsyncCulture4.exe'
' Current culture is fr-FR
' Thread 4 is running in app domain 'Domain2'
' 288,66 €
CultureInfo 对象序列化
CultureInfo序列化对象时,实际存储的所有对象为 Name 和 UseUserOverride。 它仅在具有相同含义的环境中 Name 成功反序列化。 以下三个示例演示了为什么情况并非总是如此:
CultureTypes如果属性值为 CultureTypes.InstalledWin32Cultures,并且该区域性最初是在 Windows 操作系统的特定版本中引入的,则无法在早期版本的 Windows 上将其反序列化。 例如,如果在 Windows 10 中引入了区域性,则无法在 Windows 8 上对其进行反序列化。
CultureTypes如果值为 CultureTypes.UserCustomCulture,并且对其反序列化的计算机未安装此用户自定义区域性,则无法将其反序列化。
CultureTypes如果值为 CultureTypes.ReplacementCultures,并且对其进行反序列化的计算机没有此替换区域性,则它将反序列化为同一名称,但不是所有相同的特征。 例如,如果
en-US
是计算机 A 上的替换区域性,但不是在计算机 B 上,并且 CultureInfo 引用此区域性的对象在计算机 A 上序列化并在计算机 B 上反序列化,则不会传输区域性的自定义特征。 区域性成功反序列化,但含义不同。
控制面板替代
用户可以选择通过控制面板的区域和语言选项部分替代与 Windows 的当前区域性关联的某些值。 例如,用户可以选择以不同的格式显示日期,或者对区域性使用默认值以外的货币。 通常,应用程序应遵循这些用户替代。
如果 UseUserOverride 为 true
,并且指定的区域性与 Windows 的当前区域性匹配,则 CultureInfo 使用这些替代,包括 属性返回DateTimeFormat的DateTimeFormatInfo实例属性的用户设置,以及 属性返回NumberFormat的NumberFormatInfo实例的属性。 如果用户设置与 关联的 CultureInfo区域性不兼容,例如,如果所选日历不是 之 OptionalCalendars一,则方法的结果和属性的值是未定义的。
备用排序顺序
某些区域性支持多个排序顺序。 例如:
西班牙 (西班牙) 区域性有两种排序顺序:默认的国际排序顺序和传统的排序顺序。 使用区域性名称实例化 CultureInfo 对象
es-ES
时,将使用国际排序顺序。 使用区域性名称实例化 CultureInfo 对象es-ES-tradnl
时,将使用传统的排序顺序。zh-CN
(中文 (简体,中国) ) 区域性支持两种排序顺序:按发音 (默认) 和按笔划计数。 使用区域性名称实例化 CultureInfo 对象zh-CN
时,将使用默认排序顺序。 实例化 CultureInfo 本地标识符为 0x00020804 的对象时,字符串按笔划计数排序。
下表列出了支持备用排序顺序的区域性,以及默认和备用排序顺序的标识符。
区域性名称 | 环境 | 默认排序名称和标识符 | 备用排序名称和标识符 |
---|---|---|---|
es-ES | 西班牙语(西班牙) | 国际:0x00000C0A | 传统:0x0000040A |
zh-TW | 中文(台湾) | 笔划计数:0x00000404 | Bopomofo:0x00030404 |
zh-CN | 中文(中华人民共和国) | 发音:0x00000804 | 笔划计数:0x00020804 |
zh-HK | 中文(香港特别行政区) | 笔划计数:0x00000c04 | 笔划计数:0x00020c04 |
zh-SG | 中文(新加坡) | 发音:0x00001004 | 笔划计数:0x00021004 |
zh-MO | 中文(澳门特别行政区) | 发音:0x00001404 | 笔划计数:0x00021404 |
ja-JP | 日语(日本) | 默认值:0x00000411 | Unicode:0x00010411 |
ko-KR | 韩语(韩国) | 默认值:0x00000412 | 朝鲜语 Xwansung - Unicode: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 Framework 和 .NET Core 应用中,当前区域性是每线程设置,和 CurrentCultureCurrentUICulture 属性仅反映当前线程的区域性和 UI 区域性。 在 UWP 应用中,当前区域性映射到 Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages 集合,这是一个全局设置。 CurrentCulture设置 或 CurrentUICulture 属性会更改整个应用的区域性;区域性不能按线程设置。
构造函数
CultureInfo(Int32) |
根据区域性标识符指定的区域性初始化 CultureInfo 类的新实例。 |
CultureInfo(Int32, Boolean) |
根据区域性标识符指定的区域性以及指定是否使用 Windows 中用户选择的 CultureInfo 区域性设置的值初始化 类的新实例。 |
CultureInfo(String) |
根据由名称指定的区域性初始化 CultureInfo 类的新实例。 |
CultureInfo(String, Boolean) |
根据名称指定的区域性以及指定是否使用 Windows 中用户选择的 CultureInfo 区域性设置的值初始化 类的新实例。 |
属性
Calendar |
获取区域性使用的默认日历。 |
CompareInfo |
获取为区域性定义如何比较字符串的 CompareInfo。 |
CultureTypes |
获取属于当前 CultureInfo 对象的区域性类型。 |
CurrentCulture |
获取或设置 对象, CultureInfo 该对象表示当前线程和基于任务的异步操作使用的区域性。 |
CurrentUICulture |
获取或设置 CultureInfo 对象,该对象表示资源管理器在运行时查找区域性特定资源时所用的当前用户接口区域性。 |
DateTimeFormat |
获取或设置 DateTimeFormatInfo,它定义适合区域性的、显示日期和时间的格式。 |
DefaultThreadCurrentCulture |
获取或设置当前应用程序域中线程的默认区域性。 |
DefaultThreadCurrentUICulture |
获取或设置当前应用程序域中线程的默认 UI 区域性。 |
DisplayName |
获取完整的本地化区域性名称。 |
EnglishName |
获取格式为 languagefull [country/regionfull] 的英语区域性名称。 |
IetfLanguageTag |
已弃用。 获取某种语言的 RFC 4646 标准标识。 |
InstalledUICulture |
获取表示操作系统中安装的区域性的 CultureInfo。 |
InvariantCulture |
获取不依赖于区域性(固定)的 CultureInfo 对象。 |
IsNeutralCulture |
获取一个值,该值指示当前 CultureInfo 是否表示非特定区域性。 |
IsReadOnly |
获取一个值,该值指示当前 CultureInfo 是否为只读。 |
KeyboardLayoutId |
获取活动的输入区域设置标识符。 |
LCID |
获取当前 CultureInfo 的区域性标识符。 |
Name |
获取格式为 languagecode2-country/regioncode2 的区域性名称。 |
NativeName |
获取为区域性设置的显示名称,它由语言、国家/地区以及可选脚本组成。 |
NumberFormat |
获取或设置 NumberFormatInfo,它定义适合区域性的、显示数字、货币和百分比的格式。 |
OptionalCalendars |
获取该区域性可使用的日历的列表。 |
Parent |
获取表示当前 CultureInfo 的父区域性的 CultureInfo。 |
TextInfo |
获取定义与区域性关联的书写体系的 TextInfo。 |
ThreeLetterISOLanguageName |
获取当前 CultureInfo 的语言的由三个字母构成的 ISO 639-2 代码。 |
ThreeLetterWindowsLanguageName |
获取 Windows API 中定义的由三个字母构成的语言代码。 |
TwoLetterISOLanguageName |
获取当前 CultureInfo语言的 ISO 639-1 双字母或 ISO 639-3 三字母代码。 |
UseUserOverride |
获取一个值,该值指示当前 CultureInfo 对象是否使用用户选定的区域性设置。 |
方法
ClearCachedData() |
刷新缓存的区域性相关信息。 |
Clone() |
创建当前 CultureInfo 的副本。 |
CreateSpecificCulture(String) |
创建表示与指定名称关联的特定区域性的 CultureInfo。 |
Equals(Object) |
确定指定的对象是否与当前 CultureInfo 具有相同的区域性。 |
GetConsoleFallbackUICulture() |
如果默认的图形用户界面区域性不合适,则获取适合控制台应用程序的备用用户界面区域性。 |
GetCultureInfo(Int32) |
使用特定的区域性标识符检索某个区域性的缓存的只读实例。 |
GetCultureInfo(String) |
使用特定的区域性名称检索某个区域性的缓存的只读实例。 |
GetCultureInfo(String, Boolean) |
检索某个区域性的缓存的只读实例。 |
GetCultureInfo(String, String) |
检索某个区域性的缓存的只读实例。 参数指定了一个使用 TextInfo 和 CompareInfo 对象进行初始化的区域性,而这些对象则是由另一个区域性指定的。 |
GetCultureInfoByIetfLanguageTag(String) |
已弃用。 检索只读的 CultureInfo 对象,其语言特征由指定的 RFC 4646 语言标记标识。 |
GetCultures(CultureTypes) |
获取由指定 CultureTypes 参数筛选的支持的区域性列表。 |
GetFormat(Type) |
获取一个定义如何格式化指定类型的对象。 |
GetHashCode() |
用作当前 CultureInfo 的哈希函数,适合用在哈希算法和数据结构(如哈希表)中。 |
GetType() |
获取当前实例的 Type。 (继承自 Object) |
MemberwiseClone() |
创建当前 Object 的浅表副本。 (继承自 Object) |
ReadOnly(CultureInfo) |
返回指定的 CultureInfo 对象周围的只读包装器。 |
ToString() |
返回一个字符串,该字符串包含当前 CultureInfo 的名称,其格式为 languagecode2-country/regioncode2。 |