您在询问代码点。在 UTF-16(C# 的char)中只有两种可能:
- 字符来自基本多语言平面,由单个代码单元编码。
- 字符在 BMP 之外,并使用代理高低代码单元对进行编码
因此,假设字符串有效,这将为给定字符串返回一个代码数组points:
public static int[] ToCodePoints(string str)
{
if (str == null)
throw new ArgumentNullException("str");
var codePoints = new List<int>(str.Length);
for (int i = 0; i < str.Length; i++)
{
codePoints.Add(Char.ConvertToUtf32(str, i));
if (Char.IsHighSurrogate(str[i]))
i += 1;
}
return codePoints.ToArray();
}
代理对 ? 和组合字符 ñ 的示例:
ToCodePoints("\U0001F300 El Ni\u006E\u0303o"); // ? El Niño
// { 0x1f300, 0x20, 0x45, 0x6c, 0x20, 0x4e, 0x69, 0x6e, 0x303, 0x6f } // ? E l N i n ̃◌ o
这是另一个例子。这两个代码点代表带有断音重音的第 32 个音符,都是代理对:
ToCodePoints("\U0001D162\U0001D181"); // ??
// { 0x1d162, 0x1d181 } // ? ?◌
C-normalized时,它们被分解成一个符头,组合词干、组合标志和组合重音-断奏,所有代理对:
ToCodePoints("\U0001D162\U0001D181".Normalize()); // ????
// { 0x1d158, 0x1d165, 0x1d170, 0x1d181 } // ? ? ? ?◌
请注意leppie's solution 不正确。问题是关于代码点,而不是文本元素。文本元素是代码点的组合,它们一起形成一个字素。例如,在上面的示例中,字符串中的ñ 由小写拉丁文n 后跟一个组合波浪号̃◌ 表示。 Leppie 的解决方案会丢弃任何无法归一化为单个代码点的组合字符。