Question

J'ai un IDataRecord reader que je récupérer une décimale de la façon suivante:

decimal d = (decimal)reader[0];

Pour une raison quelconque cela jette une exception coulée invalide en disant que le « cast spécifié est incorrect. »

Quand je ne reader[0].GetType() il me dit qu'il est un Int32. Pour autant que je sache, cela ne devrait pas être un problème ....

Je l'ai testé ce par cet extrait qui fonctionne très bien.

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

Cela m'a laissé me gratter la tête se demandant pourquoi il ne parvient pas à unbox l'int contenu dans le lecteur comme une décimale.

Quelqu'un sait-il pourquoi cela pourrait se produire? Y at-il quelque chose de subtil qui me manque?

Était-ce utile?

La solution

Vous ne pouvez unbox un type de valeur à son type d'origine (et la version annulable de ce type).

Par ailleurs, cela est valable (juste un raccourci pour vos deux version en ligne):

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

Pour la raison derrière cette lecture de cette Eric l'entrée de blog de Lippert: représentation et identité

Personnellement, je catégoriser les choses par la syntaxe de fonte en quatre différents types d'opérations (ils ont toutes les instructions d'IL différentes):

  1. Boxing (box d'instruction IL) et unboxing (unbox instruction IL)
  2. coulée à travers la hiérarchie de inhertiance (comme dynamic_cast<Type> en C ++, utilise instruction castclass pour vérifier l'IL)
  3. coulée entre les types primitifs (tels que static_cast<Type> en C ++, il y a beaucoup d'instructions de IL pour différents types de conversions entre des types primitifs)
  4. L'appel des opérateurs de conversion définis par l'utilisateur (au niveau IL ils sont juste méthode appelle la méthode de op_XXX appropriée).

Autres conseils

Il n'y a pas de problème en jetant un int à decimal, mais quand vous unboxing un objet vous devez utiliser le type exact que l'objet contient.

Pour unbox la valeur int en une valeur de decimal, vous devez d'abord Unbox comme un int, puis convertion en décimal:

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

L'interface IDataRecord a également des procédés pour le déballage de la valeur:

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

Voici une solution simple. Il prend soin de unboxing puis coulée en décimal. A travaillé très bien pour moi.

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

Mehrdad Afshari l'a dit:

  

Vous ne pouvez unbox un type de valeur à son type d'origine (et annulable   version de ce type).

La chose à réaliser est que il y a une différence entre la coulée et unboxing . jerryjvl avait une excellente remarque

  

Dans un sens, il est dommage que unboxing et casting regard syntaxiquement   identiques, étant donné que ce sont des opérations très différentes.

Avec:

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?
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top