2013-06-28 1 views
17

Questa domanda si applica ai dispositivi C#, .net Compact Framework 2 e Windows CE 5.C# string.IndexOf() restituisce il valore imprevisto

Ho riscontrato un errore in una DLL .net che era in uso su dispositivi CE diversi per anni, senza mostrare alcun problema. Improvvisamente, su un nuovo dispositivo Windows CE 5.0, questo bug è apparso nel codice seguente:

string s = "Print revenue receipt"; // has only single space chars 
int i = s.IndexOf(" "); // two space chars 

mi aspetto che per essere -1, tuttavia questo è stato vero solo fino ad oggi, quando indexOf improvvisamente restituito 5.

Dal momento che questo comportamento non si verifica quando si utilizza

int i = s.IndexOf(" ", StringComparison.Ordinal); 

, sono abbastanza sicuro che questo è un phenomenom basato cultura, ma non riesco a riconoscere la differenza questo nuovo dispositivo fa. È una versione per lo più identica di un dispositivo conosciuto (solo una CPU più veloce e una nuova scheda).

Entrambi i dispositivi:

  • run Windows CE 5.0 con localizzazione identico
  • System.Environment.Version rapporti '2.0.7045.0'
  • CultureInfo.CurrentUICulture e la relazione CultureInfo.CurrentCulture 'it-IT' (anche testato con 'de-DE')
  • "tutte" le chiavi di registro correlate sono uguali.

Il nuovo dispositivo ha preinstallato il CF 3.5, i cui file GAC ho rinominato sperimentalmente, senza modifiche nel comportamento descritto. Poiché a runtime viene sempre riportata la versione 2.0.7045.0, presumo che questi assembly non abbiano alcun effetto.

Anche se questo non è difficile da risolvere, non posso sopportarlo quando le cose sembrano così magiche. Qualche suggerimento quello che mi mancava?

Edit: si sta facendo più strana, vedi screenshot: screenshot

più uno: screenshot

+0

si esegue questo codice _exact_, e si ottiene 5? –

+0

non esattamente ovviamente, guarda il mio screenshot qui sopra. Ho corretto anche la domanda. Punti interessanti: * s = "Stampa entrate"; // result -1 * s = "Drucke Beleg aus"; // result -1 (!) pls scusa le mie modifiche frequenti, sono nuovo di SO. –

+0

http://i.stack.imgur.com/iGxNb.png –

risposta

0

roba cultura può davvero sembrano essere abbastanza magico su alcuni sistemi. Quello che sono venuto a fare sempre dopo anni di dolore è sempre impostare manualmente le informazioni cultura su InvariantCulture dove non desidero esplicitamente un comportamento diverso per culture diverse. Quindi il mio suggerimento sarebbe: fare che IndexOf di controllo Usa sempre la stessa informazione della cultura, in questo modo:

int i = s.IndexOf(" ", StringComparison.InvariantCulture); 
+0

Ho provato anche questo, ma è apparso lo stesso comportamento. Solo StringComparison.Ordinal lo ha risolto. Ho bisogno di sapere dove si nasconde la differenza cruciale prima che inizi il weekend ;-) Sembra anche molto difficile capire, perché due spazi potrebbero essere trattati uguali a uno, mentre 'string.Equals (" "," ");' (due spazi rispetto a uno spazio) restituisce falso ... –

+0

'String.Equals' usa il confronto ordinale; prova 'String.Compare (" "," ")' invece. – Mormegil

+0

String.Compare restituisce 1, quindi non vengono riconosciuti come uguali. –

4

Credo che avete già la risposta utilizzando una ricerca ordinale

int i = s.IndexOf(" ", StringComparison.Ordinal); 

Si può leggere una piccola sezione nella documentazione per la String Class, che ha questo da dire su questo argomento:

metodi di ricerca stringa, ad esempio String.StartsWith e String.IndexOf, anche in grado di eseguire confronti tra stringhe sensibili alla cultura o ordinali. Il seguente esempio illustra le differenze tra confronti ordinali e sensibili alla cultura usando il metodo IndexOf.Una ricerca sensibile alla cultura in cui la cultura corrente è l'inglese (Stati Uniti) considera la sottostringa "oe" per abbinare la legatura "œ". Poiché un trattino morbido (U + 00AD) è un carattere a larghezza zero, la ricerca considera il trattino basso come equivalente a Vuoto e trova una corrispondenza all'inizio della stringa. Una ricerca ordinale, d'altra parte, non trova una corrispondenza in entrambi i casi.

+2

So che questa è la risposta corretta alla domanda "come posso risolvere questo problema?" - ma la mia domanda è: "perché sta succedendo?". –

+0

Per scoprirlo ti suggerisco di iterare su ogni carattere della tua stringa di problemi in debug. Potrebbe esserci un personaggio in esso che non vedi –

+0

questo non può spiegare perché funziona su tutti gli altri dispositivi. Almeno il VS Debugger non fornisce alcun carattere nascosto quando copia + incolla in un editor esadecimale. Si prega di notare l'esempio con il ciclo sopra l'alfabeto. –

0

Il riferimento a http://msdn.microsoft.com/en-us/library/k8b1470s.aspx stati:.

"Set di caratteri includono caratteri ignorable, che sono i caratteri che non sono considerati quando si esegue un confronto linguistica o sensibili cultura In una ricerca sensibile cultura, se il valore contiene un personaggio ignorante, il risultato è equivalente alla ricerca con quel personaggio rimosso. "

Questo è da 4.5 riferimento, i riferimenti da versioni precedenti non contengono nulla del genere.

Quindi lasciami indovinare: hanno cambiato le regole da 4.0 a 4.5 e ora il secondo spazio di una sequenza di due spazi è considerato un "personaggio ignorante" - almeno se il motore riconosce la stringa come inglese testo (come nel tuo esempio stringa s), altrimenti no.

E in qualche modo sul nuovo dispositivo, viene utilizzata una 4,5 DLL anziché la versione 2.0 prevista.

un ipotesi, lo so :)

+0

Un'ipotesi molto selvaggia ma ragionevole ed educata. System.Environment.Version mostra 2.0.7045.0 in fase di esecuzione, quindi viene utilizzato CF2 SP2. Oltre a questa installazione CF2, sono presenti anche DLL CF3.5. –