Вы спрашиваете о кодовых точках . В 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-нормализовано , они разлагаются на головку, объединяя ствол, объединяя флаг и комбинируя акцент-стаккато, все суррогатные пары:
ToCodePoints("\U0001D162\U0001D181".Normalize()); // ????
// { 0x1d158, 0x1d165, 0x1d170, 0x1d181 } // ? ? ? ?◌
Обратите внимание, что решение Леппи неверно. Вопрос о кодовых точках , а не текстовых элементах . Текстовый элемент представляет собой комбинацию кодовых точек, которые вместе образуют одну графему. Например, в приведенном выше примере символ ñ
в строке представлен строчной латинской буквой n
, за которой следует тильда объединения ̃◌
. Решение Леппи отбрасывает любые объединяющие символы, которые нельзя нормализовать в одну кодовую точку.