2009-03-09 4 views
6

Dato il seguente routine di:ReSharper Trappola "Convertire a 'ritorno' affermazione"

private static object ParseNumber(string token, FieldDefinition def) 
{ 
    if (def.Fraction > 0) 
    return Double.Parse(token); 
    else 
    return Int64.Parse(token); 
} 

ReSharper mi offre la possibilità di refactoring in una dichiarazione con l'operatore ternario:

private static object ParseNumber(string token, FieldDefinition def) 
{ 
    return def.Fraction > 0 ? Double.Parse(token) : Int64.Parse(token); 
} 

Chi può individuare la trappola?

+0

http://cznp.com/s/7JM –

risposta

11

OK, passare alla risposta precedente. Poiché esiste una conversione implicita da Int64 a Double (ma non viceversa), questo sarà il tipo di risultato dell'espressione. Pertanto, quando si prevede di ottenere un numero di serie , si ottiene effettivamente un numero di casella Double (ma con un valore che originariamente proveniva da Int64.Parse).

Nel caso in cui ciò non sia abbastanza chiaro, cambiamo tutte le istruzioni return in modo tale che restituiscano solo una variabile. Ecco il codice originale:

private static object ParseNumber(string token, FieldDefinition def) 
{ 
    if (def.Fraction > 0) 
    return Double.Parse(token); 
    else 
    return Int64.Parse(token); 
} 

Convert che in modo appropriato:

private static object ParseNumber(string token, FieldDefinition def) 
{ 
    if (def.Fraction > 0) 
    { 
    double d = Double.Parse(token); 
    object boxed = d; // Result is a boxed Double 
    return boxed; 
    } 
    else 
    { 
    long l = Int64.Parse(token); 
    object boxed = l; // Result is a boxed Int64 
    return boxed; 
    } 
} 

E ora facciamo lo stesso per la versione con l'operatore condizionale:

private static object ParseNumber(string token, FieldDefinition def) 
{ 
    return def.Fraction > 0 ? Double.Parse(token) : Int64.Parse(token); 
} 

diventa

private static object ParseNumber(string token, FieldDefinition def) 
{ 
    // The Int64.Parse branch will implicitly convert to Double 
    double d = def.Fraction > 0 ? Double.Parse(token) : Int64.Parse(token); 
    object boxed = d; // *Always* a Double 
    return boxed; 
} 

MODIFICA: come richiesto pungolato, un po 'più di informazioni. Il tipo di un'espressione condizionale della forma

X ? Y : Z 

dipende dal tipo di Y e Z, che chiamerò TY e TZ. Ci sono alcune opzioni:

  • TY e TZ sono dello stesso tipo: risultato è che tipo
  • C'è una conversione implicita da TY a TZ ma non da TZ a TY: il risultato è di tipo TZ e la la conversione viene utilizzata se viene utilizzato il primo ramo.
  • C'è una conversione implicita da TZ a TY ma non da TY a TZ: il risultato è di tipo TY e la conversione è utilizzato se viene utilizzato il secondo ramo.
  • C'è una conversione implicita in entrambe le direzioni: a tempo di compilazione errore
  • ci sono conversioni in entrambi i casi: a tempo di compilazione errore

fa questo aiuto?

+0

Questo mi ha preso prima ... – leppie

+0

L'ho pubblicato circa 6 mesi su CodeProject. In effetti, è spaventoso che un numero intero sia implicitamente un doppio, anche se perde precisione. – leppie

+0

Potresti aggiungere una o due frasi sul perché la conversione implicita in double si verifica?(presumibilmente alcune proprietà dell'operatore ternario/condizionale) – Miles