2009-12-12 17 views
6

ho cercando di gestire al carattere successivo: ⨝ (http://www.fileformat.info/info/unicode/char/2a1d/index.htm)string.Empty.StartsWith (((char) 10781) .ToString()) restituisce sempre true?

Se verificare se una stringa vuota a partire da questo personaggio, restituisce sempre vero, questo non ha alcun senso! Perché?

// visual studio 2008 hides lines that have this char literally (bug in visual studio?!?) so i wrote it's unicode instead. 
char specialChar = (char)10781; 
string specialString = specialChar.ToString(); 

// prints 1 
Console.WriteLine(specialString.Length); 

// prints 10781 
Console.WriteLine((int)specialChar); 

// prints false 
Console.WriteLine(string.Empty.StartsWith("A")); 

// both prints true WTF?!? 
Console.WriteLine(string.Empty.StartsWith(specialString)); 
Console.WriteLine(string.Empty.StartsWith(((char)10781).ToString())); 

risposta

11

È possibile risolvere questo problema utilizzando ordinal StringComparison:

Dalla documentazione MSDN:

Quando si specifica sia StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase, il confronto tra stringhe sarà non -linguistico. Vale a dire, le funzioni specifiche della naturale lingua vengono ignorate quando si effettuano decisioni di confronto . Ciò significa che le decisioni si basano su semplici confronti di byte e ignorano la custodia o le tabelle di equivalenza che sono parametrizzate da cultura. Di conseguenza, impostando in modo esplicito il parametro sia la StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase, il codice spesso guadagna velocità, aumenta correttezza, e diventa più affidabile.

char specialChar = (char)10781; 


    string specialString = Convert.ToString(specialChar); 

    // prints 1 
    Console.WriteLine(specialString.Length); 

    // prints 10781 
    Console.WriteLine((int)specialChar); 

    // prints false 
    Console.WriteLine(string.Empty.StartsWith("A")); 

    // prints false 
    Console.WriteLine(string.Empty.StartsWith(specialString, StringComparison.Ordinal)); 
+0

Il confronto sensibile alla cultura per impostazione predefinita sembra una grave e disastrosa violazione del principio di minima sorpresa. Esiste qualche regola empirica per determinare quali metodi richiedono un StringComparison per ottenere un comportamento ordinale "normale" e quali no? – bobince

+0

@ bobince- hai visto questa domanda- http: // StackOverflow.com/domande/72696/che-è-generalmente-migliore-per-use-StringComparison-OrdinalIgnoreCase-o-stringcom – RichardOD

4

Nizza problema tecnico unicode ;-p

Io non sono sicuro del perché lo fa, ma in modo divertente:

Console.WriteLine(string.Empty.StartsWith(specialString)); // true 
Console.WriteLine(string.Empty.Contains(specialString)); // false 
Console.WriteLine("abc".StartsWith(specialString)); // true 
Console.WriteLine("abc".Contains(specialString)); // false 

Sto indovinando questo viene trattato un po 'come la non unendo il carattere che Jon mentioned at devdays; alcune funzioni di stringa lo vedono, e altre no. E se non lo vede, diventa "fa (una stringa) inizia con una stringa vuota", che è sempre true.

+0

+1 da parte mia. Non avevo visto le parole di Jon. – RichardOD

4

La ragione per questo è il confronto stringa predefinita è consapevole locale. Ciò significa utilizzare tabelle di dati locali per confronti (inclusa l'uguaglianza).

Molti (se non la maggior parte) caratteri Unicode non hanno valore per molte impostazioni locali e quindi non esistono (o lo fanno, ma corrispondono a qualcosa o nulla).

Vedere le voci sui pesi dei caratteri sul blog di Michael Kaplan "Sorting It All Out". This series di blog contiene molte informazioni di base (le API sono native, ma — come ho capito — i meccanismi in .NET sono gli stessi).

Versione rapida: questa è un'area complessa da aspettarsi (linguaggio normale) il confronto è difficile, questo tende a portare a cose strane con punti codice per glifi fuori dalla tua lingua.

Problemi correlati