2011-11-10 16 views
8

Duplicar posible:
Foreach can throw an InvalidCastException?¿Por qué el compilador deja esto resbalar?

Considere el siguiente bloque de código

public class Base 
{ 
} 

public class DerivedLeft : Base 
{ 
} 

public class DerivedRight : Base 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Base> list = new List<Base> { new DerivedLeft(), new DerivedRight() }; 
     foreach (DerivedLeft dl in list) 
     { 
      Console.WriteLine(dl.ToString()); 
     } 
    } 
} 

Aviso al elenco de la base a DerivedLeft de instrucción foreach. Esto compila bien (Visual Studio 2010), sin ningún error o incluso advertencia. Obviamente, en la segunda iteración de bucle obtendremos una InvalidCastException. Si me hicieran una pregunta sobre la reacción del compilador a dicho código, diría, sin duda, que el compilador no dejará que esto pase desapercibido y producirá al menos una advertencia. Pero aparentemente no es así. Entonces, ¿por qué el compilador deja pasar esto?

Respuesta

2

Debido a que la lista es de tipo List<Base> y la variable dl en el bucle foreach es de tipo DerivedLeft que tiene base como clase base. Por lo tanto, puede funcionar durante el tiempo de ejecución, pero no tiene en. El compilador no está verificando la inicialización de su lista.

+0

Creo que el compilador no comprueba la inicialización .... por ejemplo. si pongo MyOtherClass allí para que haya una excepción de tiempo de compilación –

+0

@RoyiNamir: Sí, el compilador comprueba si la inicialización es correcta, pero no comprueba si solo hay elementos coincidentes cuando alcanza el ciclo foreach. – Fischermaen

+0

correcto ............ –

0

Esperando que el compilador generará un error en esto es como esperar que para elevar un error en esto:

Base b = new DerivedRight(); 
DerivedLeft d = (DerivedLeft)b; 
+0

, de hecho, el compilador generará un error al respecto, ya que no proporcionó el nombre de variable para DerivedLeft :) – Trogvar

+0

true ......... :) – nogola

+0

Para ser justos, el molde implícito involucrado en 'foreach' no es tan obvio, a menos que uno haya codificado con 'C#' para .NET1.0 o 1.1, en el cual la falta de genéricos significaba que habría sido mucho más incómodo no tener el elenco implícito, ya que cada 'foreach' que no lo hizo 'lidiar con' objeto 'habría necesitado uno. –

Cuestiones relacionadas