StringInfo 和 TextElementEnumerator 现在符合 UAX29

在此更改之前,System.Globalization.StringInfoSystem.Globalization.TextElementEnumerator 未能正确处理所有字素群集。 一些图形被拆分为其构成组件,而不是一起保存。 现在,StringInfoTextElementEnumerator 根据最新版本的 Unicode 标准处理字形组。

此外,Microsoft.VisualBasic.Strings.StrReverse 方法(用于反转 Visual Basic 中的字符串)现在也遵循 Unicode 标准来处理字形群集。

更改描述

字素扩展字素簇是指由多个 Unicode 码位组成的单个用户感知的字符。 例如,包含泰国字符“kam”(กำ)的字符串包含以下两个字符:

  • ก (= '\u0e01')泰文字符 KO KAI
  • ำ (= '\u0e33')泰文字符 SARA AM

向用户显示时,操作系统会把这两个字符组合在一起,形成单一的显示字符(或称作图素)“kam”或 กำ。 表情符号也可以包含以这种类似方式显示的多个组合字符。

小窍门

有时 .NET 文档在提到 grapheme 时会使用术语 "text element"。

StringInfoTextElementEnumerator检查字符串并返回有关它们所包含的图形体的信息。 在 .NET Framework(所有版本)和 .NET Core 3.x 及更早版本中,这两个类使用自定义逻辑来处理某些组合类,但不完全符合 Unicode 标准。 例如, StringInfoTextElementEnumerator 类错误地将单个泰国字符“kam”拆分回其组成组件,而不是将它们放在一起。 这些类还错误地将表情符号🤷🏽‍♀️拆分为四个聚类(人耸肩、肤色修饰符、性别修饰符和不可见组合器),而不是将其合并为一个字形群组。

从 .NET 5 开始,StringInfoTextElementEnumerator 类按照 Unicode 标准附件 #29,修订版 35,第3节所定义的 Unicode 标准进行实现。 具体而言,它们现在返回所有组合类的 扩展字素群集

请考虑以下 C# 代码:

using System.Globalization;

static void Main(string[] args)
{
    PrintGraphemes("กำ");
    PrintGraphemes("🤷🏽‍♀️");
}

static void PrintGraphemes(string str)
{
    Console.WriteLine($"Printing graphemes of \"{str}\"...");
    int i = 0;

    TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(str);
    while (enumerator.MoveNext())
    {
        Console.WriteLine($"Grapheme {++i}: \"{enumerator.Current}\"");
    }

    Console.WriteLine($"({i} grapheme(s) total.)");
    Console.WriteLine();
}

在 .NET Framework 和 .NET Core 3.x 及更早版本中,图形拆分,控制台输出如下所示:

Printing graphemes of "กำ"...
Grapheme 1: "ก"
Grapheme 2: "ำ"
(2 grapheme(s) total.)

Printing graphemes of "🤷🏽‍♀️"...
Grapheme 1: "🤷"
Grapheme 2: "🏽"
Grapheme 3: "‍"
Grapheme 4: "♀️"
(4 grapheme(s) total.)

在 .NET 5 及更高版本中,图形保持在一起,控制台输出如下所示:

Printing graphemes of "กำ"...
Grapheme 1: "กำ"
(1 grapheme(s) total.)

Printing graphemes of "🤷🏽‍♀️"...
Grapheme 1: "🤷🏽‍♀️"
(1 grapheme(s) total.)

此外,从 .NET 5 开始,Microsoft.VisualBasic.Strings.StrReverse 方法(用于反转 Visual Basic 中的字符串)现在也遵循 Unicode 标准来处理字形群集。

这些更改是 .NET 中更广泛的 Unicode 和 UTF-8 改进的一部分,包括扩展字位群集枚举 API,以补充在 .NET Core 3.0 中引入的 Unicode 标量值枚举 API System.Text.Rune

已引入的版本

.NET 5.0

你不必执行任何操作。 在各种与全球化相关的方案中,你的应用将自动以更符合标准的方式行事。

受影响的 API