Ok, em .Net e C # todas as strings são codificadas como UTF-16LE . A string
é armazenado como uma sequência de caracteres. Cada um char
encapsula o armazenamento de 2 bytes ou 16 bits.
O que vemos "no papel ou na tela" como uma única letra, caractere, glifo, símbolo ou sinal de pontuação pode ser considerado um único Elemento de Texto. Conforme descrito no Anexo UNICODE nº 29 SEGMENTAÇÃO DE TEXTO DO UNICODE , cada elemento de texto é representado por um ou mais pontos de código. Uma lista exaustiva de códigos pode ser encontrada aqui .
Cada ponto de código precisa ser codificado em binário para representação interna por um computador. Como indicado, cada um char
armazena 2 bytes. Os pontos de código iguais ou inferiores U+FFFF
podem ser armazenados em um único char
. Os pontos de código acima U+FFFF
são armazenados como um par substituto, usando dois caracteres para representar um único ponto de código.
Dado o que sabemos agora que podemos deduzir, um Elemento de Texto pode ser armazenado como um char
, como um Par Substituto de dois caracteres ou, se o Elemento de Texto for representado por vários Pontos de Código, alguma combinação de caracteres únicos e Pares Substitutos. Como se isso não fosse suficientemente complicado, alguns Elementos de Texto podem ser representados por diferentes combinações de Pontos de Código, conforme descrito no Anexo Padrão 15 do Unicode, FORMULÁRIOS DE NORMALIZAÇÃO DO UNICODE .
Interlúdio
Portanto, as strings com a mesma aparência quando renderizadas podem realmente ser compostas de uma combinação diferente de caracteres. Uma comparação ordinal (byte a byte) de duas dessas seqüências detectaria uma diferença, isso pode ser inesperado ou indesejável.
Você pode recodificar as seqüências .Net. para que eles usem o mesmo formulário de normalização. Uma vez normalizado, duas seqüências com os mesmos elementos de texto serão codificadas da mesma maneira. Para fazer isso, use a função string.Normalize . No entanto, lembre-se, alguns elementos de texto diferentes se parecem. : -s
Então, o que tudo isso significa em relação à pergunta? O elemento Text '𠈓'
é representado pela única extensão de ideogramas unificados Code Point U + 20213 cjk b . Isso significa que não pode ser codificado como um único char
e deve ser codificado como Par Substituto, usando dois caracteres. É por isso que string b
é char
mais um isso string a
.
Se você precisar contar de forma confiável (consulte a advertência) o número de Elementos de Texto em um, string
você deve usar a
System.Globalization.StringInfo
classe como esta.
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);
dando a saída,
"Length a = 3"
"Length b = 3"
como esperado.
Embargo
A implementação .Net da segmentação de texto Unicode nas classes StringInfo
e TextElementEnumerator
deve ser geralmente útil e, na maioria dos casos, produzirá uma resposta que o chamador espera. No entanto, conforme declarado no Anexo Padrão 29 da Unicode, "O objetivo de corresponder às percepções do usuário nem sempre pode ser alcançado exatamente porque o texto por si só nem sempre contém informações suficientes para decidir inequivocamente os limites".