valuetype number implicita conversion cast c# casting unboxing

number - unboxing boxing c#



¿Por qué unboxing requiere la conversión explícita en C#? (7)

El boxeo es el proceso de convertir un tipo de valor en un objeto de montón administrado, que es implícito. Unboxing es el proceso inverso, para el cual el compilador requiere una conversión explícita. Ya que el boxeo almacena el tipo de datos, ¿por qué no se puede usar unboxing en lugar de pedir una conversión explícita?

class BoxUnBox { static void Main() { int i = 123; // a value type object o = i; // boxing int j = (int)o; // unboxing - Why is an explicit cast required? } }


El uso de Dynamic evita el reparto.

No para quitar nada de lo que se ha dicho, pero quería señalar que, técnicamente, el reparto no siempre es necesario para realizar el desempaquetado. La palabra clave dinámica permite que el sistema realice el desempaquetado y la conversión de forma automática. No estoy recomendando ni desalentando el uso de la dinámica, simplemente señalando su comportamiento.

static void DynamicTest() { int i = 123; // a value type object o = i; // boxing dynamic d = o; // shift to dynamic int j = d; // unboxing - No cast required }

Edición : Jeroen Mostert señala sabiamente que la palabra clave dinámica no es ningún tipo de magia que siempre hace que esto funcione. Simplemente difiere la evaluación a un comportamiento en tiempo de ejecución. Entonces, mientras que el ejemplo anterior siempre funcionará, los ejemplos más complejos definitivamente fallarán. Por lo tanto, uno debe tener cuidado al usar la palabra clave dinámica y esperar (probar / atrapar) fallas en el tiempo de ejecución. La palabra clave dinámica puede, sin embargo, ser una herramienta muy poderosa, si se utiliza con criterio.


¿Qué pasa si alguien cambia el contenido de o para decir "Hello World" . Para asegurarse de que sabe lo que está haciendo, el compilador requiere que emita explícitamente el valor en caja.

Básicamente, una conversión implícita implica que cualquier instancia o , de tipo objeto, también puede representarse como una instancia de int que claramente no es el caso. Considere por ejemplo esto:

int i = -1; long j = i;

Está claro que su variable i , que es un número entero, también puede considerarse long . Es por esto que el casting implícito es preciso aquí. Por otro lado, no todo es convertible a int sin pérdida de datos . Por lo tanto, necesita un reparto explícito para determinar: Sé que puede haber alguna pérdida de datos, sin embargo, no me importa.


Cualquier int es convertible a un objeto. No todos los objetos pueden ser lanzados a ints.


El compilador no puede garantizar lo que está dentro de su objeto. Es por eso que necesita convertir explícitamente como el valor que espera. Para el compilador:

Esto es tan peligroso.

object o = 45; int j = (int)o;

como esto:

object o = "something"; int j = (int)o;

Y eso no se puede permitir en tiempo de compilación.


La conversión puede fallar en el tiempo de ejecución, dependiendo de lo object realmente contenga su object . Cuando sería posible unboxeo implícito, puede pasar por alto los errores, ya que puede haber escrito algo que tuvo un significado diferente (ya sea que usted o usted malinterpretó el código de otra persona). El compilador requiere que emita explícitamente porque realmente debería querer ese lanzamiento. De lo contrario, podría mezclar erróneamente los tipos, lo que produce un código propenso a errores. Al ser forzado a lanzar explícitamente, se te obliga a pensar dos veces si lo que haces es correcto.


Porque un Int32 es un Object , pero un Object puede ser un Int32 . El compilador sabe qué hacer en el primer caso, pero debe decirle al compilador que sabe lo que está haciendo en el segundo caso y garantizar que se pueda realizar el desempaquetado.

La relación de herencia es direccional! El padre es diferente del niño.


Su pregunta no está relacionada únicamente con la operación de desempaquetado. En realidad, debería sonar como "¿Por qué debo usar la conversión explícita?" Considere el siguiente ejemplo:

int i = 123; long l = i; int j = (int)l; // OMG why??

La respuesta es simple y puede encontrarla en la especificación C # 6.2 Conversiones explícitas :

Las conversiones explícitas son conversiones que no siempre se puede probar que tengan éxito , las conversiones que se sabe que posiblemente pierden información y las conversiones en dominios de tipos lo suficientemente diferentes como para merecer una notación explícita.

En el ejemplo anterior puede perder información , ya que long puede contener valores que no se ajustan al rango int . Pero nunca perderá información al asignar int a long :

long l = i; // safe

En su ejemplo, necesita una conversión explícita porque no se puede probar que la conversión implícita tenga éxito siempre . Las variables de tipo de object pueden hacer referencia literalmente a cualquier tipo. ¿Qué pasa con la cadena?

object o = i; // implicit and always safe o = "Now I have a machinegun ho-ho-ho"; // safe too int j = o; // will not succeed if o is string

Analogía

La variable de objeto es como una caja negra donde se puede colocar cualquier cosa: CD de música, bolígrafo, teléfono o banana. No solo tú, sino que cualquiera puede poner algo allí. Si lo último que pusiste en una caja negra en la mañana fue un plátano, ¿puedes volver por la noche y comer lo que saques de la caja negra? Si vives solo, y la habitación está cerrada, y tu memoria es excelente, y ... entonces puedes. Y te preguntarás por qué todo el mundo comprueba el contenido de su caja antes de comerla. Pero si no vive solo o la habitación no está cerrada, o puede olvidar una sola vez que puso el teléfono en la caja ... Buen apetito