Il risultato restituito da StartsWith
è corretto. Per impostazione predefinita, la maggior parte dei metodi di confronto delle stringhe esegue confronti sensibili alla cultura utilizzando la cultura corrente, non le sequenze di byte semplici. Sebbene il tuo line
inizi con una sequenza di byte identica a sub
, la sottostringa che rappresenta non è equivalente nella maggior parte (o tutte) le culture.
Se davvero si vuole un confronto che tratta stringhe come sequenze di byte semplici, utilizzare l'overload:
line.StartsWith(sub, StringComparison.Ordinal); // true
Se si desidera che il confronto sia case-insensitive:
line.StartsWith(sub, StringComparison.OrdinalIgnoreCase); // true
Ecco un altro Esempio familiare:
var line1 = "café"; // 63 61 66 E9 – precomposed character 'é' (U+00E9)
var line2 = "café"; // 63 61 66 65 301 – base letter e (U+0065) and
// combining acute accent (U+0301)
var sub = "cafe"; // 63 61 66 65
Console.WriteLine(line1.StartsWith(sub)); // false
Console.WriteLine(line2.StartsWith(sub)); // false
Console.WriteLine(line1.StartsWith(sub, StringComparison.Ordinal)); // false
Console.WriteLine(line2.StartsWith(sub, StringComparison.Ordinal)); // true
Negli esempi precedenti, line2
inizia con la stessa sequenza di byte di sub
, seguita da un accento acuto di combinazione (U + 0301) da applicare allo e
finale. line1
utilizza precomposed character per é
(U + 00E9), quindi la sequenza di byte non corrisponde a quella di sub
.
Nella semantica del mondo reale, in genere non si considera cafe
una sottostringa di café
; il e
e é
sono trattati come caratteri distinti. Che é
sia rappresentato come una coppia di caratteri che iniziano con e
è un dettaglio di implementazione interna dello schema di codifica (Unicode) che non dovrebbe influire sui risultati. Ciò è dimostrato dal precedente esempio in contrasto café
e café
; non ci si aspetterebbero risultati diversi se non si intende specificamente un confronto ordinale (byte per byte).
Adattando questa spiegazione tuo esempio:
string line = "Mìng-dĕ̤ng-ngṳ̄"; // 4D EC 6E 67 2D 64 115 324 6E 67 2D 6E 67 1E73 304
string sub = "Mìng-dĕ̤ng-ngṳ"; // 4D EC 6E 67 2D 64 115 324 6E 67 2D 6E 67 1E73
Ogni carattere NET rappresenta un'unità di codice UTF-16, i cui valori sono riportati nelle osservazioni sopra. Le prime 14 unità di codice sono identiche, motivo per cui il tuo confronto char-by-char viene valutato come vero (proprio come StringComparison.Ordinal
). Tuttavia, la 15a unità di codice in line
è il macron combinante, ◌̄ (U+0304), che combina con il precedente ṳ
(U+1E73) per fornire ṳ̄
.
Usa una cultura invarianti. Vedi, ad esempio, http://stackoverflow.com/q/492799/1364007 –
Non conosco il Vietnamita. C'è una linea sopra l'ultima 'u'. Non lo rende una lettera diversa? * Modifica: * Mi sono perso che stai stampando le lunghezze, il che sembra mostrare che la linea è considerata * un altro * personaggio ... interessante. –
Mi sembra che 'StartsWith()' DOVREBBE restituire false, perché (come fa notare Jonathon), 'line' in realtà non inizia con' sub'. –