2012-10-04 17 views
8

Acabo de recibir esta prueba de un colega que me está volviendo loco. Para este fragmento de código:Tipo anulable GetType() arroja la excepción

var x = new Int32?(); 
string text = x.ToString(); // No exception 
Console.WriteLine(text); 
Type type = x.GetType(); // Bang! 

¿Por qué la primera parte .ToString() funciona sin lanzar una excepción y entonces la llamada a GetType() lanza una NullReferenceException?

Respuesta

17

ToString es overridden in Nullable<T>, por lo que no se requiere el uso de un boxeo para realizar la llamada.

GetType() no es un método virtual, por lo que no está (y no puede) sobrescrito, por lo que el valor se almacena antes de que se realice la llamada ... y el boxeo un valor nulo de un tipo de valor que admite valores NULL referencia nula

La razón para el boxeo está en la sección 7.5.5 de la especificación C# 4:

Si M es un miembro de la función de instancias que se declaren en una referencia de tipo :

  • ..
  • Si el tipo de E es value-type, se realiza una conversión de boxeo (4.3.1) para convertir E al tipo object y E se consideran del tipo object en los siguientes pasos. En este caso, M sólo podía ser un miembro de System.Object

Tenga en cuenta que si tiene que:

var x = new Int32?(10); 

acabaría con el tipo de ser el mismo que typeof(int), de nuevo debido a boxeo. No hay forma de crear un valor foo tal que foo.GetType() devuelve un tipo de valor que se puede nulos, utilizando el método normal GetType(). (Se puede crear un nuevoGetType() método por supuesto , pero eso es una cuestión secundaria :)

(El uso de "Bang!", Sugiere el autor de dicho cuestionario mí puede ser. Disculpas por volviendo loco si ese es el caso.)

+0

Bien ... pero ¿por qué entonces reemplazar la última línea con: var boxed = (Int32) x; arroja InvalidOperationException en su lugar? ¿No es ese boxeo y debería arrojar la misma excepción? – kabaros

+0

@kabaros: No, eso no es boxeo en absoluto, ni 'Int32?' Ni 'Int32' son tipos de referencia. Es una conversión explícita descrita en la sección 6.2.3 de la especificación C# 4. –

+1

Oh, sí, por supuesto, eso tiene perfecto sentido. Muchas gracias. Gran libro por cierto, así que te perdonamos por volvernos locos :) – kabaros

Cuestiones relacionadas