在此更改之前,System.Globalization.StringInfo 和 System.Globalization.TextElementEnumerator 未能正确处理所有字素群集。 一些图形被拆分为其构成组件,而不是一起保存。 现在,StringInfo 和 TextElementEnumerator 根据最新版本的 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 标准。 例如, StringInfo 和 TextElementEnumerator 类错误地将单个泰国字符“kam”拆分回其组成组件,而不是将它们放在一起。 这些类还错误地将表情符号🤷🏽♀️拆分为四个聚类(人耸肩、肤色修饰符、性别修饰符和不可见组合器),而不是将其合并为一个字形群组。
从 .NET 5 开始,StringInfo 和 TextElementEnumerator 类按照 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
建议的措施
你不必执行任何操作。 在各种与全球化相关的方案中,你的应用将自动以更符合标准的方式行事。