全球化 API 在 Windows Server 2019 上使用 ICU 库
当在 Windows Server 2019 上运行时,.NET 7 及更高版本使用 Unicode 国际组件 (ICU) 库来实现全球化功能。 自 .NET 5 以来,Windows 的非服务器版本一直在使用 ICU。 但是,.NET 7 引入了在早期 Windows 客户端版本中加载 ICU 的支持,特别是 Windows 10 版本 1703、1709、1803 和 1809。
旧行为
在 .NET 5 和 .NET 6 中,.NET 库使用本地语言支持 (NLS) API 来实现 Windows Server 2019 上的全球化功能。 例如,NLS 函数用于比较字符串,获取区域性信息,并在适当的区域中执行字符串大小写。 此行为也适用于 Windows 10 客户端版本,例如 1703、1709、1803 和 1809。
新行为
从 .NET 7 开始,如果应用在 Windows Server 2019 或 Windows 10 客户端版本 1703、1709、1803 和 1809 上运行,.NET 库默认使用ICU全球化 API。 (非服务器 Windows 版本已从 .NET 5 开始使用 ICU,因此这些版本没有变化。)
行为差异
即使你不知道正在使用全球化设施,你也可能会在应用中看到更改。 下例显示了你可能会看到的行为更改之一,但还有其他一些行为更改。
货币符号
请考虑使用以下代码,它使用货币格式说明符 C
设置字符串格式。 当前线程的区域性设置为仅包括语言(而非国家或地区)的区域性。
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("de");
string text = string.Format("{0:C}", 100);
- 在 Windows Server 2019 或 Windows 10 客户端版本 1703、1709、1803 和 1809 上的 .NET 5 和 .NET 6 中,文本值为
"100,00 €"
。 - 在 Windows Server 2019 或 Windows 10 客户端版本 1703、1709、1803 和 1809 上的 .NET 7 中,文本值为
"100,00 ¤"
,它使用国际货币符号而不是欧元。 在 ICU 中,这种设计是指,货币是国家或地区的属性,而不是语言。
更改原因
- .NET 引入了一些依赖于 ICU 库的 API,例如 TimeZoneInfo.TryConvertIanaIdToWindowsId(String, String)。 想要在 Windows Server 2019 上使用此类 API 的用户需要使用 ICU App Local 功能手动部署 ICU 库及其二进制文件。 这不是一个很好的解决方案,因为代码位于的库可能无法强制使用采用该库的应用或服务安装 ICU 库。
- 如果 Windows Server 2019 由云平台(如 Azure)自动提供,则部署的服务不一定知道它将在此类服务器上运行。 此外,服务所有者必须管理是否/何时部署 ICU 二进制文件。 另外,每个使用 Windows Server 2019 部署到云的服务如果想要使用新的 .NET ICU 相关 API,都需要使用该服务部署 ICU 二进制文件。 这会使服务器磁盘的大小膨胀。
- 默认情况下,一些用户更喜欢使用 ICU,因为它更符合 Unicode 标准。
引入的版本
.NET 7
建议的操作
如果正在使用 Windows Server 2019 或 Windows 10 客户端版本 1703、1709、1803 或 1809 上的 .NET 7,建议在寄送应用或服务之前对其进行测试,从而确保行为符合预期且不中断任何用户。
如果你想要继续使用 NLS 全球化 API,则可以将运行时开关设置为还原到该行为。 有关可用开关的详细信息,请参阅 .NET 全球化和 ICU 一文。
受影响的 API
- System.Span<T>
- System.String
- System.Globalization 命名空间中的大多数类型
- System.Array.Sort(对字符串数组进行排序时)
- System.Collections.Generic.List<T>.Sort()(当列表元素为字符串时)
- System.Collections.Generic.SortedDictionary<TKey,TValue>(当键为字符串时)
- System.Collections.Generic.SortedList<TKey,TValue>(当键为字符串时)
- System.Collections.Generic.SortedSet<T>(当集包含字符串时)