c# - separador - ¿Por qué no puedo desempaquetar un int como un decimal?
mostrar solo 2 decimales en c# (4)
Aquí hay una solución simple. Se encarga de unboxing y luego de lanzar a decimal. Funcionó bien para mí
decimal d = Convert.ToDecimal(reader[0]); // reader[0] is int
Tengo un IDataRecord reader
que estoy recuperando un decimal de la siguiente manera:
decimal d = (decimal)reader[0];
Por alguna razón, esto arroja una excepción de conversión inválida que dice que "el reparto especificado no es válido".
Cuando lo hago, el reader[0].GetType()
me dice que es un Int32. Hasta donde yo sé, esto no debería ser un problema ...
He probado esto con este fragmento que funciona bien.
int i = 3750;
decimal d = (decimal)i;
Esto me ha dejado rascándome la cabeza preguntándome por qué no está descomprimiendo el int contenido en el lector como un decimal.
¿Alguien sabe por qué esto podría estar ocurriendo? ¿Hay algo sutil que me estoy perdiendo?
Mehrdad Afshari lo dijo:
Solo puede desvincular un tipo de valor a su tipo original (y la versión que admite valores nulos de ese tipo).
Lo que hay que darse cuenta es que hay una diferencia entre lanzar y desempaquetar . jerryjvl tuvo un excelente comentario
En cierto sentido, es una pena que el unboxing y el casting sean sintácticamente idénticos, ya que son operaciones muy diferentes.
Fundición:
int i = 3750; // Declares a normal int
decimal d = (decimal)i; // Casts an int into a decimal > OK
Boxeo / 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?
No hay problema para convertir un int
a decimal
, pero cuando está desempaquetando un objeto, debe usar el tipo exacto que contiene el objeto.
Para desempaquetar el valor int
en un valor decimal
, primero lo desempaqueta como un int y luego lo convierte a decimal:
decimal d = (decimal)(int)reader[0];
La interfaz IDataRecord también tiene métodos para desempaquetar el valor:
decimal d = (decimal)reader.GetInt32(0);
Solo puede desvincular un tipo de valor a su tipo original (y la versión que admite valores nulos de ese tipo).
Por cierto, esto es válido (solo una abreviatura para su versión de dos líneas):
object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it''s a widening conversion
Por la razón detrás de esto lea esta entrada del blog de Eric Lippert: Representación e identidad
Personalmente, clasifico las cosas hechas por sintaxis de molde en cuatro tipos diferentes de operación (todas tienen diferentes instrucciones de IL):
- Boxeo (instrucción IL de la
box
) yunbox
(instrucciónunbox
IL) - Casting a través de la jerarquía de inherencia (como
dynamic_cast<Type>
en C ++, utiliza la instrucción decastclass
IL para verificar) - Casting entre tipos primitivos (como
static_cast<Type>
en C ++, hay muchas instrucciones de IL para diferentes tipos de moldes entre tipos primitivos) - Llamar a los operadores de conversión definidos por el usuario (en el nivel IL solo son llamadas al método apropiado
op_XXX
).