Символы C # и UTF-16 - PullRequest
       11

Символы C # и UTF-16

7 голосов
/ 30 марта 2009

Возможно ли в C # использовать символы UTF-32, не находящиеся в плоскости 0, в качестве символа?

string s = ""; // valid
char c = ''; // generates a compiler error ("Too many characters in character literal")

А в s он представлен двумя символами, а не одним.

Edit: я имею в виду, есть ли символьный тип строки AN с полной поддержкой юникода, UTF-32 или UTF-8 на символ? Например, если я хочу цикл for для символов utf-32 (возможно, не в plane0) в строке.

Ответы [ 3 ]

9 голосов
/ 12 мая 2009

Класс string представляет кодированный блок текста в кодировке UTF-16, и каждый char в string представляет кодовое значение UTF-16.

Хотя не существует типа BCL, представляющего одну кодовую точку Юникода, существует поддержка символов Юникода за плоскостью 0 в форме перегрузок методов, принимающих string и индекс вместо просто char. Например, статический метод GetUnicodeCategory & # xfeff; (char) в классе System.Globalization.CharUnicodeInfo имеет соответствующий GetUnicodeCategory & # xfeff; (string,int) метод, который распознает простой символ или суррогатную пару, начиная с указанного индекса.


Для итерации по текстовым элементам в string вы можете использовать методы класса System.Globalization.StringInfo . Здесь «текстовый элемент» соответствует одному символу, отображаемому на экране. Это означает, что простые символы ("a"), объединяющие символы ("a\u0304\u0308" = "a & # x0304; & # x0308;") и суррогатные пары ("\uD950\uDF21" = "& # xD950; & # xDF21;") будут все должны рассматриваться как один текстовый элемент.

В частности, статический метод GetTextElementEnumerator позволит вам перечислять каждый текстовый элемент в string (пример кода см. На связанной странице MSDN).

4 голосов
/ 30 марта 2009

Я знаю эту проблему только из Java и проверил документацию на char, прежде чем ответить, и, действительно, поведение очень похоже на .NET / C # и Java.

Кажется, что действительно char определено как 16-битный и определенно не может содержать ничего вне плоскости 0. Только String / string способен обрабатывать эти символы. В массиве char он будет представлен как два суррогатных символа .

3 голосов
/ 09 мая 2009

C # System.String прекрасно поддерживает UTF-32, но вы не можете перебирать строку, как будто это массив System.Char или использовать IEnumerable.

например:

// iterating through a string NO UTF-32 SUPPORT
for (int i = 0; i < sample.Length; ++i)
{
    if (Char.IsDigit(sample[i]))
    {
        Console.WriteLine("IsDigit");
    }
    else if (Char.IsLetter(sample[i]))
    {
        Console.WriteLine("IsLetter");
    }
}

// iterating through a string WITH UTF-32 SUPPORT
for (int i = 0; i < sample.Length; ++i)
{
    if (Char.IsDigit(sample, i))
    {
        Console.WriteLine("IsDigit");
    }
    else if (Char.IsLetter(sample, i))
    {
        Console.WriteLine("IsLetter");
    }

    if (Char.IsSurrogate(sample, i))
    {
        ++i;
    }
}

Обратите внимание на тонкую разницу в вызовах Char.IsDigit и Char.IsLetter. И это String.Length - это всегда число 16-битных «символов», а не количество «символов» в смысле UTF-32.

Не по теме, но поддержка UTF-32 совершенно не нужна для приложения, работающего с международными языками, если только у вас нет конкретного бизнес-кейса для неясного исторического / технического языка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...