Гаразд, у .Net та C # всі рядки кодуються як UTF-16LE . А stringзберігається як послідовність символів. Кожна charкапсула зберігає 2 байти або 16 біт.
Те, що ми бачимо «на папері чи екрані» як окрему букву, символ, гліф, символ або розділовий знак, можна розглядати як єдиний текстовий елемент. Як описано в стандартному додатку Unicode № 29 СЕГМЕНТАЦІЯ ТЕКСТУ UNICODE , кожен текстовий елемент представлений однією або кількома кодовими точками. Вичерпний список кодів можна знайти тут .
Кожну кодову точку потрібно закодувати у двійковий код для внутрішнього представлення комп'ютером. Як зазначено, кожен charзберігає 2 байти. Кодові точки в і нижче U+FFFFможна зберігати в одній char. Кодові точки вище U+FFFFзберігаються у вигляді сурогатної пари, використовуючи дві символи для представлення однієї кодової точки.
З огляду на те, що ми знаємо, що ми можемо зробити, текстовий елемент може бути збережений як один char, як сурогатний пара з двох знаків або, якщо текстовий елемент представлений кількома кодовими точками, деякою комбінацією одиничних знаків і сурогатних пар. Як би це не було досить складним, деякі текстові елементи можуть бути представлені різними комбінаціями точок коду, як описано в, стандартному додатку Unicode, № 15, НОРМАЛІЗАЦІЙНИЙ ФОРМ UNICODE .
Інтермедія
Таким чином, рядки, які виглядають однаково при рендерингу, насправді можуть складатися з різної комбінації символів. Порядкове (байт у байті) порівняння двох таких рядків виявило б різницю, це може бути несподівано або небажано.
Ви можете перекодувати рядки .Net. щоб вони використовували ту саму Форму нормалізації. Після нормалізації два рядки з однаковими текстовими елементами будуть закодовані однаково. Для цього використовуйте функцію string.Normalize . Однак пам’ятайте, деякі різні текстові елементи схожі між собою. : -s
Отже, що це все означає стосовно питання? Текстовий елемент '𠈓'представлений єдиним розширенням уніфікованих ідеографів cjk U + 20213 cjk b . Це означає, що він не може бути кодований як єдиний charі повинен бути кодований як сурогатний пара, використовуючи дві символи. Ось чому string bодин charдовший string a.
Якщо вам потрібно надійно (див. Застереження) підрахувати кількість текстових елементів у a, stringви повинні використовувати такий
System.Globalization.StringInfoклас.
using System.Globalization;
string a = "abc";
string b = "A𠈓C";
Console.WriteLine("Length a = {0}", new StringInfo(a).LengthInTextElements);
Console.WriteLine("Length b = {0}", new StringInfo(b).LengthInTextElements);
даючи вихід,
"Length a = 3"
"Length b = 3"
як і очікувалося.
Caveat
Реалізація тексту тексту Unicode у класах StringInfoта TextElementEnumeratorкласах має бути загалом корисною та в більшості випадків дасть відповідь, яку очікує абонент. Однак, як зазначено у стандартному додатку Unicode, доданий №29, "мета співставлення сприйняття користувачів не завжди може бути точно досягнута, оскільки сам по собі текст не завжди містить достатньо інформації для однозначного визначення меж".