Ok, in .Net e C # tutte le stringhe sono codificate come UTF-16LE . A string
è memorizzato come una sequenza di caratteri. Ciascuno char
incapsula la memoria di 2 byte o 16 bit.
Ciò che vediamo "su carta o schermo" come una singola lettera, carattere, glifo, simbolo o segno di punteggiatura può essere considerato come un singolo elemento di testo. Come descritto nella SEGMENTAZIONE DEL TESTO UNICODE standard Unicode n. 29 , ogni elemento di testo è rappresentato da uno o più punti di codice. Un elenco esaustivo di codici è disponibile qui .
Ogni punto di codice deve essere codificato in binario per la rappresentazione interna da un computer. Come detto, ognuno char
memorizza 2 byte. I punti di codice in o sotto U+FFFF
possono essere memorizzati in un singolo char
. I punti di codice sopra U+FFFF
sono memorizzati come coppia surrogata, usando due caratteri per rappresentare un singolo punto di codice.
Dato ciò che ora sappiamo di poter dedurre, un elemento di testo può essere memorizzato come uno char
, come coppia surrogata di due caratteri o, se l'elemento di testo è rappresentato da più punti di codice una combinazione di singoli caratteri e coppie di surrogati. Come se ciò non fosse abbastanza complicato, alcuni elementi di testo possono essere rappresentati da diverse combinazioni di punti di codice come descritto in, Unicode Standard Annex # 15, UNICODE NORMALIZATION FORMS .
Interludio
Quindi, le stringhe che sembrano uguali quando vengono renderizzate possono effettivamente essere costituite da una diversa combinazione di caratteri. Un confronto ordinale (byte per byte) di due di queste stringhe rileverebbe una differenza, ciò potrebbe essere inatteso o indesiderabile.
È possibile ricodificare le stringhe .Net. in modo che utilizzino lo stesso modulo di normalizzazione. Una volta normalizzati, due stringhe con gli stessi elementi di testo verranno codificate allo stesso modo. Per fare ciò, utilizzare la funzione string.Normalize . Tuttavia, ricorda, alcuni elementi di testo diversi sono simili tra loro. :-S
Quindi, cosa significa tutto ciò in relazione alla domanda? L'elemento di testo '𠈓'
è rappresentato dalla singola estensione del punto di codice U + 20213 cjk ideogrammi unificati b . Ciò significa che non può essere codificato come singolo char
e deve essere codificato come coppia surrogata, utilizzando due caratteri. Questo è il motivo per cui string b
uno è char
più lungo string a
.
Se devi contare in modo affidabile (vedi avvertenza) il numero di elementi di testo in a string
, dovresti usare la
System.Globalization.StringInfo
classe in questo modo.
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 l'output,
"Length a = 3"
"Length b = 3"
come previsto.
Avvertimento
L'implementazione .Net della segmentazione del testo Unicode nelle classi StringInfo
e TextElementEnumerator
dovrebbe essere generalmente utile e, nella maggior parte dei casi, produrrà una risposta che il chiamante si aspetta. Tuttavia, come indicato nell'Allegato n. 29 dello standard Unicode, "L'obiettivo di abbinare le percezioni degli utenti non può sempre essere raggiunto esattamente perché il solo testo non contiene sempre informazioni sufficienti per decidere inequivocabilmente i limiti".