J'ai un IDataRecord reader
Dont je récupère une décimale comme suit:
decimal d = (decimal)reader[0];
Pour une raison quelconque, cela déclenche une exception de transtypage non valide indiquant que le "transtypage spécifié n'est pas valide".
Quand je fais reader[0].GetType()
cela me dit que c'est un Int32. Pour autant que je sache, cela ne devrait pas poser de problème ...
J'ai testé cela par cet extrait qui fonctionne très bien.
int i = 3750;
decimal d = (decimal)i;
Cela m'a laissé me gratter la tête en me demandant pourquoi il ne parvient pas à déballer l'int. Contenu dans le lecteur sous forme décimale.
Est-ce que quelqu'un sait pourquoi cela pourrait se produire? Y a-t-il quelque chose de subtil qui me manque?
Vous pouvez uniquement décompresser un type de valeur vers son type d'origine (et la version nullable de ce type).
Au fait, cela est valable (juste un raccourci pour votre version à deux lignes):
object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion
Pour la raison derrière cela, lisez ceci Entrée de blog d'Eric Lippert: Représentation et identité
Personnellement, je classe les choses faites par cast syntaxe en quatre types d'opérations différents (ils ont tous des instructions IL différentes):
box
instruction IL) et unboxing (unbox
instruction IL)dynamic_cast<Type>
en C++, utilise castclass
instruction IL pour vérifier)static_cast<Type>
en C++, il existe de nombreuses instructions IL pour différents types de transtypages entre types primitifs)op_XXX
méthode).Voici une solution simple. Il prend en charge le déballage et le transtypage en décimal. Ça a bien marché pour moi.
decimal d = Convert.ToDecimal(reader[0]); // reader[0] is int
Il n'y a aucun problème lors de la conversion d'un int
en decimal
, mais lorsque vous déballez un objet, vous devez utiliser le type exact qu'il contient.
Pour décompresser la valeur int
dans une valeur decimal
, vous devez d'abord la décompresser en tant qu'int, puis la convertir en décimal:
decimal d = (decimal)(int)reader[0];
L'interface IDataRecord a également des méthodes pour déballer la valeur:
decimal d = (decimal)reader.GetInt32(0);
Mehrdad Afshari l'a dit:
Vous pouvez uniquement décompresser un type de valeur vers son type d'origine (et la version nullable de ce type).
La chose à réaliser est que il y a une différence entre le casting et le déballage. jerryjvl a fait une excellente remarque
Dans un sens, il est dommage que le déballage et le casting semblent syntaxiquement identiques, car ce sont des opérations très différentes.
Fonderie:
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?