2014-12-15 14 views
8

Il mio problema è che String.IndexOf restituisce -1. Mi aspetto che restituisca 0.Confronto IndexOf e stringhe ordinali

I parametri:

text = C:\\Users\\User\\Desktop\\Sync\\̼ (nota il carattere Combining Seagull Below)

stringToTrim = C:\\Users\\User\\Desktop\\Sync\\

Quando controllo per l'indice, utilizzando int index = text.IndexOf(stringToTrim);, il valore di index è -1. Ho trovato che l'uso di un confronto tra stringhe ordinale ha risolto questo problema mio:

int index = text.IndexOf(stringToTrim, StringComparison.Ordinal); 

la lettura on-line, un sacco di caratteri Unicode (come U+00B5 e U+03BC) mappa per lo stesso simbolo, quindi sarebbe una buona idea per espandere su questo e normalizzare entrambe le stringhe:

int index = text.Normalize(NormalizationForm.FormKD).IndexOf(stringToTrim.Normalize(NormalizationForm.FormKD), StringComparison.Ordinal); 

È questo l'approccio corretto per controllare a quale indice di una stringa contiene tutti i caratteri sequenziali di un'altra stringa? Quindi l'idea è, normalizzi quando vuoi controllare che i simboli siano una corrispondenza, ma non ti normalizzi quando vuoi controllare i caratteri con i loro valori codificati (quindi permetti simboli duplicati)? Inoltre, qualcuno potrebbe spiegare perché int index = text.IndexOf(stringToTrim); non ha trovato una corrispondenza all'inizio della stringa? In altre parole, cosa sta effettivamente facendo sotto le coperte? Mi sarei aspettato che iniziasse a cercare i caratteri dall'inizio della stringa fino alla fine della stringa.

+0

ho copiato/incollato questo in LINQPad ed ho ottenuto "0" indietro - forse non capisco caratteri che conciliano. – dnord

+0

@dnord Prova questo: '" C: \\ Utenti \\ Utente \\ Desktop \\ Sync \\ ̼ ".IndexOf (" C: \\ Utenti \\ Utente \\ Desktop \\ Sync \\ ");' Assicurati di copiare questo testo interamente/esattamente da qui! – Alexandru

+0

(Grazie ha funzionato.) Quindi sono sicuramente d'accordo con la prima risposta del valutatore qui sotto: o combinando i personaggi cambia il personaggio precedente (combinando) o hai trovato un bug strano che almeno Microsoft ti ha avvisato. – dnord

risposta

6

Il comportamento ha perfettamente senso per me. Stai utilizzando un carattere di combinazione, che è combinato con con il carattere precedente, trasformandolo in un carattere diverso, uno che non corrisponde al carattere '\\' che hai specificato alla fine della stringa di ricerca. Ciò impedisce di trovare l'intera stringa che stai cercando. Se invece avessi cercato "C:\\Users\\User\\Desktop\\Sync", l'avrebbe trovato.

L'utilizzo di StringComparison.Ordinal indica a .NET di ignorare le varie regole per i caratteri e osservare solo il loro valore ordinale esatto. Questo sembra fare ciò che volevi, quindi sì e hellip: è quello che dovresti fare.

"L'approccio corretto" dipende interamente dal comportamento che si desidera. Un sacco di manipolazione delle stringhe coinvolge il testo presentato o fornito dall'utente e dovrebbe essere fatto in un modo consapevole della cultura e Unicode. Altre volte, non è desiderabile. È importante selezionare l'approccio giusto per le tue esigenze.

1

Sì, è necessario utilizzare StringComparison.Ordinal per garantire che la cultura venga ignorata durante il confronto del valore. È necessario soprattutto per tutte le stringhe che sono considerate come invarianti di cultura "di default". Ciò include i percorsi dei file.

Quando non si utilizza StringComparison.Ordinal) è possibile introdurre sottili bug: http://msdn.microsoft.com/en-us/library/dd465121(v=vs.110).aspx

Quando i dati di stringa culturalmente indipendenti, come i tag XML, tag HTML, nomi utente, percorsi di file, ed i nomi dei sistemi oggetti, sono interpretati come se fossero sensibili alla cultura, il codice dell'applicazione può essere soggetto a bug sottili, prestazioni scarse e, in alcuni casi, problemi di sicurezza .

Alcuni vantaggio collaterale di StringComparison.Ordinal è una migliore performance: http://msdn.microsoft.com/en-us/library/ms973919.aspx