2009-05-14 17 views
8

Prueba el siguiente códigoImposible (o apto) a la lista <int> .Cast <Enum>()?

public enum Color 
{ 
    Blue=1, 
    Red=2, 
    Green=3 
} 

public List<Color> ConvertColorEnum() 
{ 
    var intColor = new List<int>(){1,2,3}; 
    return intColor.Cast<Color>().ToList(); 
} 

¿Cree que el ConvertColorEnum() devolverá una lista de color, es decir, List<Color>(){Color.Blue, Color.Red, Color.Green}?

Probé esto en 2 máquinas, una con .net 3.5 (mscorlib versión 2.0.50727.1433), otra con .net 3.5 SP1 (mscorlib versión 2.0.50727.3082). Los resultados fueron diferentes: el .net 3.5 arrojó un InvalidCastException porque no pudo convertir el entero a enum, mientras que el .net 3.5 SP1 se pudo ejecutar con éxito, con los resultados correctos devueltos.

¿Alguien quiere probar esto en su máquina e informar el resultado o explicar por qué es así?

Respuesta

4

Puede leer sobre la diferencia entre el SP1 y el lanzamiento original de .net 3.5 framework in the release notes.

Aquí es lo que dice en este tema en particular:

En expresiones de consulta LINQ más colecciones no genéricas tales como System.Collections.ArrayList, la de cláusula de la consulta es reescrita por el compilador para incluir una llamada al operador de fundición . Transformar convierte todos los tipos de elemento al tipo especificado en la cláusula from en la consulta . Además, en la versión de lanzamiento original de de Visual C# 2008, el operador de conversión también realiza algunas conversiones de tipo de valor y conversiones definidas por el usuario. Sin embargo, estas conversiones se realizan por utilizando la clase System.Convert en su lugar de la semántica de C# estándar. Estas conversiones también causan problemas significativos de rendimiento de en ciertos escenarios de .En Visual C# 2008 SP1, el operador de conversión se modifica para lanzar una InvalidCastException para el tipo de valor numérico y las conversiones definidas por el usuario . Este cambio elimina tanto la semántica no estándar de C# fundido como el problema de rendimiento. Este cambio se ilustra en el siguiente ejemplo de .

También puede obtener más detalles en this blog post.

17

Si desea que funcione de cualquier manera, use Select en su lugar.

return intColor.Select(i=>(Color)i).ToList(); 

En cuanto a la razón ...?

+0

@marc, estoy a punto de decir que está en el 50K, pero su dolorosamente cerca de 49.999;) –

+0

molesto, ¿verdad? –

+0

Buena idea, pero ¿no cree que intColor.Cast () es más sucinto y legible? – Graviton

4

El método de extensión Cast hace uso de un iterador que, en el siguiente movimiento, almacena el resultado del enumerador original en una variable de objeto (tan encajonado según sea necesario) y luego intenta convertirlo al tipo de resultado.

Los tipos de valores en forma de recuadro no responden a la operación de envío de la misma forma que si estuvieran desempaquetados (donde son posibles varias conversiones automáticas), sino que solo permiten la conversión a su formato original no incluido.

Me imagino que la aplicación previa de la extensión moldeada fue ya sea haciendo completamente diferente o tenía algún carcasa especial para este tipo de enumeración para convertir a una forma integral (esto es complicado, ya que debe hacer frente a todas las formas posibles)

La respuesta de Marc en cuanto a la solución correcta es completamente correcta y en realidad es más eficiente que el elenco de todos modos por los motivos de boxeo antes mencionados.

+0

Ah sí, 5__ab - No lo detecté ;-p –

+0

fácil de perder - tengo que agradecer los nombres sintetizados del compilador, Desearía que MS facilitara el proceso de carga de la fuente completa. Tal vez debería escribir un plugin reflector a tiempo para tomarlo del servidor de símbolos ... – ShuggyCoUk

Cuestiones relacionadas