2011-02-07 20 views
7

Sto riscontrando un problema nel far funzionare correttamente TryParse. Ho una lista di valori che sono quasi certo siano validi (dato che provengono da un altro componente del nostro sistema) ma vorrei assicurarmi che ci sia una corretta gestione degli errori.TryParse fallito con numeri negativi

Ecco un elenco esempio di miei valori:

20,00
20,00
-150,00

e qui è il metodo che ho originariamente scritto:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal successful; 
       Decimal.TryParse(xElement.Value, out successful); 
       if (successful > 0) 
        totalValue += Decimal.Parse(xElement.Value); 
      } 
      return totalValue; 
     } 

La variabile 'successo' restituiva false per -150,00, quindi ho aggiunto NumberStyles:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal successful; 
       Decimal.TryParse(xElement.Value, NumberStyles.AllowLeadingSign, null, out successful); 
       if (successful > 0) 
        totalValue += Decimal.Parse(xElement.Value, NumberStyles.AllowLeadingSign); 
      } 
      return totalValue; 
     } 

Tuttavia, ora che ho NumberStyles, nessun numero verrà analizzato! Sono contento di avere IFormatProvider impostato su null poiché questo è tutto nel nostro sistema. Qualcuno vede cosa potrei fare male?

+2

Perché sei l'analisi di due volte? – SLaks

risposta

3

Le altre risposte hanno avuto l'idea giusta per quanto riguarda il modo corretto di utilizzare Decimal.TryParse. Tuttavia, se dovessi scrivere il metodo in questione, mi piacerebbe usare LINQ to lavorare con gli oggetti LINQ to XML:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
{ 
    return summaryValues 
     .Sum(el => 
      { 
       decimal value; 
       if (Decimal.TryParse(el.Value, out value)) 
        return value; 
       return 0M; 
      }); 
} 

Questa versione funziona esattamente allo stesso modo, ma utilizza il metodo per calcolare il Enumerable.Sum totale. Tutto quello che devo fornire è una funzione inline che estrae i valori decimali da un XElement.

+0

Grazie, ho finito per usare questo codice. – Jeannine

11

Questo non è il modo in cui si suppone di utilizzare TryParse.

TryParse ritorna un valore booleano (vero/falso), in modo che il codice di cui sopra dovrebbe essere:

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal valueReturned; 
       bool successful = Decimal.TryParse(xElement.Value, out valueReturned); 
       if (successful) 
        totalValue += valueReturned; 
      } 
      return totalValue; 
     } 

o più brevemente,

private decimal CalculateValue(IEnumerable<XElement> summaryValues) 
     { 
      decimal totalValue = 0; 

      foreach (XElement xElement in summaryValues) 
      { 
       decimal valueReturned; 
       if (Decimal.TryParse(xElement.Value, out valueReturned)) 
        totalValue += valueReturned; 
      } 
      return totalValue; 
     } 
+1

'if (! Decimal.TryParse (/ * derp * /) getta nuovo InvalidOperationException (" OMG WTF LOL ")' – Will

+0

@Will In questo esempio dovrebbe avere un'eccezione come questa, anche se si fida ragionevolmente della fonte. potrebbe avere una situazione in cui ti aspetti e vuoi ignorare silenziosamente le stringhe che non vengono analizzate –

1

vostro successo sta per essere negativo per un valore negativo essere analizzato. il tuo if (successful > 0) è quello che ti sta facendo saltare in aria.

Se hanno intenzione quasi positivamente per essere valori validi, provare a utilizzare Convert.ToDecimal:

decimal val = Convert.ToDecimal(xElement.Value); 

In caso contrario, modificare la logica un po 'per essere più simile a:

decimal val; 
if (Decimal.TryParse(xElement.Value, out val)){ 
    // valid number 
} 
0

vorrei suggerire a indicare a XElement quale valore del nodo deve cercare come:

XElement.Element("nodename").Value 

Instea d di XElement.Value. almeno questo è quello che vorrei fare :)

4

Altri stanno spiegando come farlo nel modo giusto, ma non spiegando veramente cosa stai facendo male.

Il punto in cui si sta utilizzando "riuscito" non è il valore di successo, è il numero effettivo che viene analizzato. Quindi se stai analizzando "-150.00", ovviamente, il successo sarà negativo. Il valore out di TryParse è il valore parsed effettivo e il valore booleano che indica se il processo ha avuto esito positivo o meno è il valore restituito. Utilizzando quello che hai per aiutare a capire sarebbe qualcosa di simile:

string inputValue = "-150.00"; 
decimal numericValue; 
bool isSucessful = Decimal.TryParse(inputValue , out numericValue); 

In questo caso, isSuccessful sarà vero, numericValue sarà -150.Quando si utilizza i valori forniti dall'utente al posto di quello hardcoded che ho usato in precedenza si vorrà controllare:

if(isSuccessful) 
{ 
    // Do something with numericValue since we know it to be a valid decimal 
} 
else 
{ 
    // Inform User, throw exception, etc... as appropriate, Don't use numericValue because we know it's wrong. 
} 
+0

Sì, questa era la radice del problema Grazie per avermi edumato :) – Jeannine

0

Arriva da Google. Risposta per me è stata la cultura in entrata era sbagliato - in particolare in un file JSON in arrivo.

Usa

totalValue += decimal.Parse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture); 

o

bool successful = decimal.TryParse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out value); 
Problemi correlati