2011-08-03 13 views

Respuesta

27

GetType() es un método de object.
Para invocarlo, la estructura Nullable<T> debe estar enmarcada.

Esto se puede ver en el código IL:

//int? x = 5; 
IL_0000: ldloca.s 00 
IL_0002: ldc.i4.5  
IL_0003: call  System.Nullable<System.Int32>..ctor 

//Console.WriteLine(x.GetType()); 
IL_0008: ldloc.0  
IL_0009: box   System.Nullable<System.Int32> 
IL_000E: callvirt System.Object.GetType 
IL_0013: call  System.Console.WriteLine 

tipos anulables se tratan de forma especial por CLR; es imposible tener una instancia en caja de un tipo que admite nulos.
En su lugar, el boxeo de tipo anulable dará como resultado una referencia nula (si HasValue es falso), o el valor encuadrado (si hay un valor).

Por lo tanto, la instrucción box System.Nullable<System.Int32> da como resultado Int32 en caja, no en caja Nullable<Int32>.

Por lo tanto, es imposible para GetType() a alguna vez return Nullable<T>.

Para ver esto más claramente, mira el siguiente código:

static void Main() 
{ 
    int? x = 5; 
    PrintType(x); 
} 
static void PrintType<T>(T val) { 
    Console.WriteLine("Compile-time type: " + typeof(T)); 
    Console.WriteLine("Run-time type: " + val.GetType()); 
} 

Esto imprime

tipo en tiempo de compilación: System.Nullable`1 [System.Int32]
Run- tipo de hora: System.Int32

4

No se puede box un anulable.

se podría hacer algo como esto:

public static Type GetCompilerType<T>(this T @object) 
{ 
    return typeof (T); 
} 

int? x = 5; 
Console.WriteLine(x.GetCompilerType()); 
// prints: 
// System.Nullable`1[System.Int32] 
+0

Identificador de espera; 'objeto' es una palabra clave – SLaks

+0

@slaks, gracias ... se olvidó de arreglar eso. –

8

GetType() no es virtual, y por lo tanto se define sólo en object. Como tal, para realizar la llamada, primero se debe incluir el Nullable<Int32>. Nullables tiene reglas especiales de boxeo, por lo que solo el valor Int32 está encuadrado, y ese es el tipo informado.

+1

¿Hay alguna razón particular por la que Nullable (y otras estructuras, para el caso) no debería haber definido sus propios métodos GetType que sombrearían los de Object? Parece increíblemente tonto que si Foo es un tipo de valor, Foo.GetType() debería requerir la creación de un nuevo objeto Heap para almacenar el contenido encuadrado de Foo, cuando de hecho ese contenido será ignorado. ¿No sería más eficiente simplemente sombrear Foo.GetType() con un método que simplemente devolviera el objeto Tipo apropiado? – supercat

+0

@supercat No estoy seguro de estar calificado para responder esa pregunta.Una cosa que diré es que las estructuras que se pueden anular son tontas de muchas maneras, debido al hecho de que básicamente se agregaron después del hecho, en lugar de incorporarse al lenguaje desde el principio. El punto general aún se cumple, supongo, ya que necesita colocar una variable 'int' para llamar a' GetType() 'también. Como siempre se van a cargar los tipos en los que esto debería importar, es posible que se trate de una concesión de consistencia de espacio/documentación. Tal vez Eric Lippert puede arrojar algo más de luz. – dlev

+1

@supercat 'GetType()' no tiene sentido para un tipo 'sellado', porque puede usar' typeof() '. 'Nullable ', como todas las 'struct's, está sellado implícitamente. Si realmente no tiene sentido llamar a 'GetType()', seguro, se hará funcionar si no hay razón para no hacerlo, pero eso es todo, no espere demasiado esfuerzo en la optimización. – hvd

1

Porque el tipo de "5" es int.

Si desea detectar si un tipo es anulable, y el tipo subyacente, usar algo como esto:

public static Type GetActualType(Type type, out bool isNullable) 
{ 
    Type ult = Nullable.GetUnderlyingType(type); 
    if (ult != null) 
    { 
     isNullable = true; 
     return ult; 
    } 
    isNullable = false; 
    return type; 
} 
+0

Eso no es correcto, SLaks. Mire la documentación aquí: http://msdn.microsoft.com/en-us/library/system.nullable.getunderlyingtype.aspx que dice: "Valor de retorno Tipo: System.Type El argumento de tipo del parámetro nullableType, si el parámetro nullableType es un tipo genérico anulable cerrado; de lo contrario, nulo. " –

+0

Tienes razón; Yo extraví. Sin embargo, esto no responde la pregunta. 'x' ** es ** un' int? '. – SLaks

+0

Y "5" es un int. –

Cuestiones relacionadas