2013-05-10 4 views
1

Я пытаюсь определить последствия кодировки символов для программной системы, которую планирую, и при выполнении теста обнаружил что-то странное.Unicode SMP «character» в C# char

Насколько я знаю, C# внутренне использует UTF-16, который (насколько мне известно) охватывает каждую кодовую точку Unicode, используя два 16-битных поля. Поэтому я хотел сделать некоторые литералы символов и намеренно выбрал и 얤, потому что первая из плоскости SMP, а последняя - из плоскости BMP. Полученные результаты:

char ch1 = '얤'; // No problem 
char ch2 = ''; // Compilation error "Too many characters in character literal" 

Что происходит?

Из-за этого вопроса, если у меня есть строка «얤얤», она отображается правильно в MessageBox, однако, когда я преобразовываю ее в char [], используя ToCharArray, я получаю массив с четырьмя элементами, а не тремя. Также String.Length отображается как четыре, а не три.

Я что-то упустил?

+0

Вероятно, это сохранение сложного символа в виде кодовой точки Юникода, которая обычно имеет два символа в длине. –

+0

@ RaymondChen острый глаз ... Я пробовал несколько разных поисков и не нашел ничего подходящего! – 2013-05-10 16:44:08

+0

Могу ли я как-то закрыть этот вопрос как дубликат? – 2013-05-10 16:50:51

ответ

0

Ваш исходный файл может быть не сохранен в UTF-8 (что рекомендуется при использовании специальных символов в источнике), поэтому компилятор может фактически увидеть последовательность байтов, которая смущает его. Вы можете убедиться, что, открыв исходный файл в шестнадцатеричном редакторе, байт (ы), который вы увидите вместо своего персонажа, скорее всего, будет другим.

Если он еще не включен, вы можете включить этот параметр в Инструменты-> Параметры-> Документы в Visual Studio (я использую 2008) - опция Save documents as Unicode when data cannot be saved in codepage.

Как правило, лучше указать специальные символы, используя последовательность символов.

В этом MSDN article описано использование последовательностей \uxxxx для указания нужного символьного кода в Юникоде. В этом blog entry перечислены все возможные escape-последовательности C# - причина, по которой я включаю это, потому что он упоминает использование \ xnnn - избегает использования этого формата: это переменная длина версии \u, и это может вызвать проблемы в некоторых ситуациях (не в ваших , хоть).

MSDN article указывает, почему назначение символов не подходит: кодовая точка для рассматриваемого символа - это> FFFF, который находится за пределами диапазона для типа char.

Что касается строковой части вопроса, то ответ заключается в том, что символ SMP представляется в виде двух значений char. This SO question содержит некоторый код, показывающий, как получить коды из строки, это связано с использованием StringInfo.GetTextElementEnumerator

Все это было освещено в комментариях к этому ответу, поэтому я только что привел соответствующую информацию в эту ответьте и теперь согласитесь с этим.

+0

Ответ был на самом деле в статье MSDN, которую вы цитировали ... точка кода для 1D6C03, и в статье говорится, что коды выше 10FFFF не поддерживаются. Благодаря! – 2013-05-10 16:06:59

+0

Строго мой предыдущий комментарий неверен, статья MSDN гласит, что «символ Unicode в диапазоне U + 10000 до U + 10FFFF не разрешен в символьном литерале и представлен с использованием суррогатной пары Unicode в строковом литерале», но затем он продолжает говорить, что в строках символы Unicode за пределами 10FFFF не поддерживаются. Просто для уточнения ... лимит символов недействителен, потому что кодовая точка выше FFFF, строковый литерал недействителен, потому что точка кода выше 10FFFF – 2013-05-10 16:13:05

+0

То, что я не понимаю, - это то, почему моя строка с кодовой точкой> 10FFFF отображается правильно в MessageBox ... – 2013-05-10 16:15:10