2010-07-21 20 views
6

Como sabemos, los objetos C# tienen un puntero a su tipo, por lo que cuando llama al GetType(), comprueba ese puntero y devuelve el tipo real de un objeto. Pero si hago esto:¿Qué sucede realmente cuando haces GetType()?

A objA = new A(); 
object obj = (object)objA; 
if (obj.GetType() == typeof(object)) ; // this is true 

Pero lo que sucede aquí object obj = (object)objA;? ¿Crea algún tipo de objeto de referencia, que hace referencia a objA, pero tiene un puntero de tipo a object, o es un objeto completamente nuevo, que simplemente apunta a las mismas propiedades, campos, etc. como objA? Ciertamente, ahora puede acceder a ambos objetos y tendrán un tipo diferente, pero apuntan a los mismos datos. ¿Cómo funciona?

La otra pregunta es: ¿se garantiza GetType() para devolver el tipo real de un objeto? Por ejemplo, supongamos que hay un método con la firma void Method(object sender) y pasamos el objeto del tipo A como parámetro. ¿sender.GetType() tipo de devolución A o object? ¿Y por qué?

Otra cosa difícil es que puedes hacer (A)obj y funcionará. ¿Cómo funciona CLR ahora que obj fue una vez del tipo A?

Estaría encantado de que alguien pudiera desglosarlo un poco más claro que "C# through CLR".

Actualización. Malo, debería haber ejecutado el código antes de publicar la pregunta. Por lo tanto, si GetType() realmente siempre devuelve el tipo real, todas las demás preguntas se aclararán también.

+11

Su pregunta se basa en una premisa totalmente falsa. La línea marcada "this is true" no es verdadera. Intenta escribir un pequeño programa que realmente se compile y se ejecute si no me crees. GetType() siempre devuelve * el tipo de tiempo de ejecución real * del objeto. Todas sus preguntas se basan en la suposición incorrecta de que el tipo de tiempo de compilación tiene algo que ver con eso. No es asi. –

+0

@Eric, bien que está bien, y eso es lo que siempre pensé, se distrajo con un código diferente comportamiento en un proyecto, mi mal. –

Respuesta

22

Como sabemos, los objetos C# tienen un puntero a su tipo, por lo que cuando llama a GetType() comprueba ese puntero y devuelve el tipo real de un objeto.

Correcto.

si hago esto:

class A {} 
class P 
{ 
    public static void Main() 
    { 
     A objA = new A(); 
     object obj = (object)objA; 
     bool b = obj.GetType() == typeof(object) ; // this is true 
    } 
} 

No, eso es falso. ¡Intentalo!

Pero, ¿qué ocurre aquí object obj = (object) objA ;?

La referencia que está en objA se copia a la variable obj. (A menos que A es un tipo de valor, en cuyo caso se encajona y una referencia a la caja se copia en obj.)

tampoco crea una especie de objeto de referencia, que hace referencia a objA, pero tiene un tipo puntero para objetar, o es un objeto completamente nuevo, que simplemente apunta a las mismas propiedades, campos, etc. como objA?

Ninguno. Copia la referencia, punto. Está completamente sin cambios.

Ciertamente, puede acceder a ambos objetos ahora y tendrán un tipo diferente, pero apuntan a los mismos datos. ¿Cómo funciona?

No lo es. La pregunta se basa en una suposición que es falsa. No tendrán diferentes tipos. Ellos son la misma referencia. Las variables de tienen diferentes tipos, pero eso es irrelevante; usted no está pidiendo la variable de su tipo, que está pidiendo los contenidos de la variable para su tipo.

¿GetType() garantiza devolver el tipo real de un objeto?

para sus propósitos, sí. Hay situaciones poco claras que implican interoperabilidad COM donde no.

Por ejemplo, supongamos que hay un método con el método de firma nulo (remitente del objeto) y pasamos el objeto de tipo A como parámetro. Will sender.GetType() devuelve el tipo A u objeto?

Tipo A.

y por qué?

Porque ese es el tipo de objeto.

Otra cosa difícil es que puedes hacer (A) obj y funcionará. ¿Cómo funciona CLR ahora que obj fue una vez de tipo A?

El compilador C# genera una instrucción de clase secundaria. La instrucción castclass realiza una comprobación en tiempo de ejecución para verificar que la referencia del objeto implementa el tipo deseado. Si no es así, el CLR arroja una excepción.

+0

Eric, por curiosidad, ¿cómo puedo distinguir el tipo de tiempo de ejecución de una variable del tipo de objeto al que se refiere? ¿No hay dos niveles/fases para el sistema de tipos? es decir Compilar tipo de tiempo (utilizado para producir errores para cosas como esta: ((objeto) mystring) .Substring()), y el tipo de tiempo de ejecución (de GetType()) que se utiliza para la reflexión. Cuando falla la compilación, se debe a la verificación de tipos en tiempo de compilación (es decir, no se comprueba el tipo de tiempo de ejecución en absoluto, por lo que no utiliza los tipos de variable o instancia per se). ¿El propio tipo de variable (más que el tipo de las cosas a las que hace referencia) solo se manifiesta en tiempo de compilación? –

+0

Lo siento, cuando digo distinguir, debería decir "distinguir en tiempo de ejecución a través de la reflexión". –

+1

@Andrew: el compilador C# conoce el tipo de variable en tiempo de compilación y el verificador CLR en tiempo de ejecución. El verificador verifica que el código pueda verificarse de forma segura al garantizar que a ninguna variable se le haya asignado un valor incompatible con su tipo. Si su pregunta es "¿puedo reflexionar sobre el tipo de una variable local usando reflexión?", No, no puede porque * las variables locales no están expuestas por reflexión *. Por supuesto, puede reflexionar sobre el tipo de campo o un parámetro formal. –

Cuestiones relacionadas