2010-12-21 23 views
16

Me preguntaba por qué se controlan algunos modelos en C# en tiempo de compilación, mientras que en otros casos la responsabilidad recae en CLR. Al igual que arriba, ambos son incorrectos pero se manejan de una manera diferente.Recopilación en tiempo de ejecución y en tiempo de ejecución C#

class Base { } 
class Derived : Base { } 
class Other { } 

static void Main(string[] args) 
{ 
    Derived d = (Derived)new Base();  //Runtime  InvalidCastException 
    Derived d = (Derived)new Other(); //Compile-time Cannot convert type... 
} 

Mientras lee "C# en profundidad" que he encontrado la información sobre este tema en el autor dice:
"Si las manchas del compilador que en realidad es imposible que ese elenco de trabajar, que va desencadenar un error de compilación, y si está teóricamente permitido pero realmente incorrecto en el momento de la ejecución, el CLR emitirá una excepción ".

¿El término 'teóricamente' Mean conectado por jerarquía de herencia (y otros otra afinidad entre objetos?) O es un negocio interno del compilador?

+1

Una gran pregunta. Espero que alguien más iluminado que yo me proporcione una explicación. –

Respuesta

20
  • Las actualizaciones se pueden verificar en tiempo de compilación: el sistema de tipo garantiza que el reparto tiene éxito.
  • Los downcasts no pueden (en general) verificarse en tiempo de compilación, por lo que siempre se verifican en tiempo de ejecución.
  • Los tipos no relacionados no se pueden enviar el uno al otro.

El compilador solo considera los tipos estáticos. El tiempo de ejecución comprueba el tipo dinámico (tiempo de ejecución). En cuanto a los ejemplos:

Other x = new Other(); 
Derived d = (Derived)x; 

El tipo estático de x es Other. Esto no está relacionado con Derived, por lo que la conversión falla en tiempo de compilación.

Base x = new Base(); 
Derived d = (Derived)x; 

El tipo estático de x es ahora Base. Algo del tipo Basepodría tener el tipo dinámico Derived, por lo que este es un downcast. En general, el compilador no puede saber del tipo estático x si el tipo de tiempo de ejecución es Base, Derived, de alguna otra subclase de Base. Entonces, la decisión de si el elenco está permitido se deja al tiempo de ejecución.

+2

+1: gran explicación :) – LaGrandMere

+1

Entonces, ¿uno puede suponer que el compilador también verifica sobrecargas de operador de molde implícito/explícito? –

1

Si su variable es de Base tipo, se puede construir teóricamente por el constructor Derived, por lo que es una variable de tipo Derived en realidad. En tiempo de compilación, el compilador no se molesta en tratar de averiguar si en cada caso particular, es posible un downcast (que representa una variable del tipo Base como una entidad del tipo Derived).

Su muestra es simple: crea una nueva clase y la lanza de inmediato. ¿Pero qué sucede si obtiene Base desde otro lugar, por ejemplo, alguna llamada a un método? El compilador simplemente no puede "adivinar" cuál es el método que va a devolver y, por lo tanto, arrojar no arrojar un error.

Cuando elije Other, el compilador ve que no hay posibilidad de que Other sea en realidad y arroja una excepción.