D'accord, en .Net et C # toutes les chaînes sont encodées en UTF-16LE . A string
est stocké sous la forme d'une séquence de caractères. Chacun char
encapsule le stockage de 2 octets ou 16 bits.
Ce que nous voyons «sur papier ou écran» comme une seule lettre, caractère, glyphe, symbole ou signe de ponctuation peut être considéré comme un élément de texte unique. Comme décrit dans l' annexe 29 de la norme Unicode SEGMENTATION DE TEXTE UNICODE , chaque élément de texte est représenté par un ou plusieurs points de code. Une liste exhaustive des codes peut être trouvée ici .
Chaque point de code doit être encodé en binaire pour une représentation interne par un ordinateur. Comme indiqué, chacun char
stocke 2 octets. Les points de code à ou en dessous U+FFFF
peuvent être stockés dans un seul char
. Les points de code ci U+FFFF
- dessus sont stockés en tant que paire de substitution, en utilisant deux caractères pour représenter un seul point de code.
Compte tenu de ce que nous savons maintenant que nous pouvons déduire, un élément de texte peut être stocké comme un seul char
, comme une paire de substitution de deux caractères ou, si l'élément de texte est représenté par plusieurs points de code, une combinaison de caractères uniques et de paires de substitution. Comme si cela n'était pas assez compliqué, certains éléments de texte peuvent être représentés par différentes combinaisons de points de code comme décrit dans l'Annexe n ° 15 de la norme Unicode, FORMULAIRES DE NORMALISATION UNICODE .
Interlude
Ainsi, les chaînes qui se ressemblent lors du rendu peuvent en fait être constituées d'une combinaison différente de caractères. Une comparaison ordinale (octet par octet) de deux de ces chaînes détecterait une différence, cela peut être inattendu ou indésirable.
Vous pouvez ré-encoder les chaînes .Net. afin qu'ils utilisent le même formulaire de normalisation. Une fois normalisées, deux chaînes avec les mêmes éléments de texte seront encodées de la même manière. Pour ce faire, utilisez la fonction string.Normalize . Cependant, rappelez-vous que certains éléments de texte différents se ressemblent. : -s
Alors, qu'est-ce que tout cela signifie par rapport à la question? L'élément de texte '𠈓'
est représenté par l' extension d'idéographes unifiés de point de code U + 20213 cjk b . Cela signifie qu'il ne peut pas être codé comme un seul char
et doit être codé comme paire de substitution, en utilisant deux caractères. C'est pourquoi il string b
y en a un char
plus long string a
.
Si vous avez besoin de compter de manière fiable (voir la mise en garde) le nombre d'éléments de texte dans un, string
vous devez utiliser la
System.Globalization.StringInfo
classe comme ceci.
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);
donnant la sortie,
"Length a = 3"
"Length b = 3"
comme prévu.
Caveat
L'implémentation .Net de la segmentation de texte Unicode dans les classes StringInfo
et TextElementEnumerator
devrait être généralement utile et, dans la plupart des cas, produira une réponse attendue par l'appelant. Cependant, comme indiqué dans l' annexe 29 de la norme Unicode, "l'objectif de faire correspondre les perceptions des utilisateurs ne peut pas toujours être atteint exactement parce que le texte seul ne contient pas toujours suffisamment d'informations pour décider sans ambiguïté des limites."