Domanda

Ho un IDataRecord reader che sto recuperando un decimale da come segue:

decimal d = (decimal)reader[0];

Per qualche motivo questo genera un'eccezione getto valida dicendo che il "Cast specificato non è valido."

Quando faccio reader[0].GetType() mi dice che si tratta di un Int32. Per quanto ne so, questo non dovrebbe essere un problema ....

Ho testato questo fuori da questo frammento di codice che funziona bene.

int i = 3750;
decimal d = (decimal)i;

Questo mi ha lasciato graffiare la mia testa chiedendosi il motivo per cui non riesce a unboxing INT contenuta nel lettore come un decimale.

Qualcuno sa perché questo potrebbe essere che si verificano? C'è qualcosa di sottile che mi manca?

È stato utile?

Soluzione

È possibile unboxing solo un tipo di valore al suo tipo originale (e la versione nullable di quel tipo).

A proposito, questo è valido (solo una scorciatoia per la versione a due righe):

object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion

Per la ragione alla base di questo leggere questo Eric blog di Lippert: Rappresentazione e identità

Personalmente, ho classificare le cose fatte dalla sintassi fusione in quattro diversi tipi di operazioni (tutti hanno diverse istruzioni IL):

  1. Pugilato (box istruzioni IL) e unboxing (unbox istruzioni IL)
  2. Casting attraverso la gerarchia inhertiance (come dynamic_cast<Type> in C ++, utilizza castclass istruzioni IL verificare)
  3. Casting tra i tipi primitivi (come static_cast<Type> in C ++, ci sono un sacco di istruzioni IL per diversi tipi di calchi tra tipi primitivi)
  4. Calling operatori di conversione definiti dall'utente (a livello IL sono solo le chiamate di metodo al metodo op_XXX appropriato).

Altri suggerimenti

Non v'è alcun problema in che esprimono un int a decimal, ma quando si sono unboxing di un oggetto è necessario utilizzare il tipo esatto che l'oggetto contiene.

Per unboxing il valore int in un valore decimal, in primo luogo Unbox come un int, poi gettarlo ai decimali:

decimal d = (decimal)(int)reader[0];

L'interfaccia IDataRecord ha anche metodi per unboxing del valore:

decimal d = (decimal)reader.GetInt32(0);

Ecco una soluzione semplice. Si prende cura di unboxing e poi colata a decimale. Ha lavorato bene per me.

decimal d = Convert.ToDecimal(reader[0]);  // reader[0] is int

Mehrdad Afshari ha detto:

  

È possibile solo unboxing un tipo di valore al suo tipo originale (e la nullable   versione di quel tipo).

La cosa da capire è che v'è una differenza tra casting e unboxing . jerryjvl ha una chiara osservazione

  

In un certo senso è un peccato che unboxing e lanciando un'occhiata sintatticamente   identici, poiché sono operazioni molto diverse.

Casting:

int i = 3750; // Declares a normal int
decimal d = (decimal)i; // Casts an int into a decimal > OK

Boxe / unboxing:

object i = 3750; // Boxes an int ("3750" is similar to "(int)3750")
decimal d = (decimal)i; // Unboxes the boxed int into a decimal > KO, can only unbox it into a int or int?
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top