2010-03-30 8 views
15

breve e versione dolce:decimal.TryParse() scende leader "1"

Su una macchina fuori di circa un centinaio di macchine di prova decimal.TryParse() è la conversione "1,01" per 0,01


Ok, sembrerà pazzesco, ma portami con me ...

Abbiamo un'applicazione client che comunica con un servizio web tramite JSON e quel servizio restituisce un valore decimale come una stringa così lo memorizziamo come una stringa nel nostro modello oggetto:

[DataMember(Name = "value")] 
public string Value { get; set; } 

Quando viene visualizzato quel valore sullo schermo, viene formattato con un numero specifico di posizioni decimali. Quindi il processo che usiamo è stringa -> decimale poi decimale -> stringa.

L'applicazione è attualmente sottoposta a test finali ed è in esecuzione su oltre 100 macchine, dove tutto funziona correttamente. Tuttavia su una macchina se il valore decimale ha un "1" iniziale allora viene sostituito da uno zero. Ho aggiunto semplice registrazione per il codice in modo che assomiglia a questo:

Log("Original string value: {0}", value); 
decimal val; 
if (decimal.TryParse(value, out val)) 
{ 
    Log("Parsed decimal value: {0}", val); 
    string output = val.ToString(format, CultureInfo.InvariantCulture.NumberFormat); 
    Log("Formatted string value: {0}", output); 
    return output; 
} 

Sulla mia macchina - qualsiasi ogni altra macchina client - l'uscita file di log è:

  • valore stringa originale: 1,010 mila
  • Parsed valore decimale: 1,010000
  • formattato valore stringa: 1,01

Sulla macchina difettosa l'output è:

  • valore stringa originale: 1,010000
  • analizzato valore decimale: 0,010000
  • valore stringa formattata: 0,01

Così sembrerebbe che il metodo decimal.TryParse sia in errore.

cose che abbiamo provato:

  • disinstallare e reinstallare l'applicazione client
  • disinstallare e reinstallare .NET 3.5 SP1
  • Confrontando impostazioni internazionali della macchina difettosa per i numeri (con English (United Kingdom)) a quelli di una macchina funzionante - nessuna differenza.

Qualcuno ha visto qualcosa di simile o ha qualche suggerimento? Sto rapidamente a corto di idee ...


Mentre stavo scrivendo questo un po 'di informazioni è venuto in: Passare un valore stringa di "10000" per convertire.ToInt32() restituisce 0, in modo che sembra anche cadere le principali 1.


Ulteriori prove basate su osservazioni:

  • 1,01 -> 0.01
  • 111.01 -> 11.01
  • 123.01 -> 23,01
  • 231,01 -> 231,01
  • 01,01 -> 1,01

Quindi sembrerebbe che riguarda solo 1s e solo se sono il primo carattere della stringa. Molto strano, ma almeno è coerente.

+1

Strano. Cosa succede con altre cifre come "123" o "321"? –

+0

RAM danneggiata nella macchina? Hai provato a eseguire qualcosa come memtest86? –

+0

Questa è una pessima idea, ma se pre-pad con uno zero ...? – spender

risposta

16

Sono in grado di riprodurre i risultati. Considerare:

public NumberFormatInfo OneIsPositiveSignFormat() 
{ 
    NumberFormatInfo custom = new NumberFormatInfo(); 
    custom.PositiveSign = "1"; 
    return custom; 
} 

E poi:

if (decimal.TryParse(value, NumberStyles.Number, OneIsPositiveSignFormat(), out val)) 

La cosa è: Impostazioni internazionali non mostra l'attuale segno positivo, e soprattutto: non è stata impostata la cultura durante l'analisi del numero di .

Il valore può provenire da varie località: potrebbe provenire dal Registro di sistema, come le impostazioni predefinite del sistema, o le impostazioni predefinite potrebbe essere stato fissato dal codice:

CultureInfo customCulture = (CultureInfo)CultureInfo.InvariantCulture.Clone(); 
customCulture.NumberFormat = OneIsPositiveSignFormat(); 
Thread.CurrentThread.CurrentCulture = customCulture; 
+1

Risposta interessante, ma si pone la domanda che se le Impostazioni internazionali non consentono di impostare il segno positivo e le impostazioni regionali dell'OP sono le stesse delle altre macchine, come è stato possibile modificare il segno positivo? Non sono in disaccordo con te, si adatta perfettamente agli esempi, sono solo curioso. –

+2

E abbiamo un vincitore! Ha appena eseguito il seguente codice sulla sua macchina: Console.WriteLine (System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PositiveSign); e emette "1". Ora, ho solo bisogno di capire come cambiare questo ... –

+0

Scommetto che era un programma di terze parti che ha fatto questo. Che mostruosità. – Kugel

-1

vedere come sono impostate le impostazioni internazionali per questo computer potrebbe essere che "." è impostato come separatore delle migliaia e non come separatore decimale. Prova a utilizzare Decimal.TryParse (String, NumberStyles, IFormatProvider, out Decimal val) e passa NumberFormatInfo creato con il separatore decimale "."

+2

OP ha già detto che non ci sono differenze nelle impostazioni regionali - più se 1.000 è stato inserito quando '.' era un separatore di migliaia, avrebbe dato 1000, non 0. –

Problemi correlati