2012-02-17 13 views
6

Teniendo en cuenta este código:Enum.GetValues ​​(typeof (....)) no devolver la enumeración adecuada valores

public enum Enum1 
{ 
    ONE, 
    TWO 
} 

public enum Enum2 
{ 
    A, 
    B 
} 

Este código devuelve UNO, DOS:

foreach (Enum1 e in Enum.GetValues(typeof(Enum1))) 
{ 
    Console.WriteLine(e); 
} 

Pero este código, en lugar de fallar (debido a que se utiliza con Enum2 etypeof(Enum1)), devuelve A, B:

foreach (Enum2 e in Enum.GetValues(typeof(Enum1))) 
{ 
    Console.WriteLine(e); 
} 

¿Por qué?

Respuesta

9

Porque debajo de las cubiertas, las entradas son solo entradas; la segunda devuelve los valores de Enum1, pero realmente esos valores son solo 0 y 1. Cuando se lanzan esos valores al tipo Enum2, estos siguen siendo válidos y corresponden a los valores "A" y "B".

+1

Por supuesto que sí ... ¡Qué tonto! Olvidé que en las enumeraciones de C# son realmente fantasiosas.Estaba más acostumbrado a las enumeraciones de Java que son clases completas. Es triste que el compilador no lo capte ... – JohnDoDo

+6

@JohnDoDo: El compilador no lo detecta porque "foreach (Enum2 e ..." hace una conversión ** explícita ** - un molde, efectivamente - de el tipo de colección al tipo de variable de bucle. Es legal * cast * '(Enum2) enum1', por lo que es legal hacer lo mismo implícitamente con * foreach *. Recuerde, foreach fue inventado antes de los genéricos; tenía un ArrayList de cadenas, querría poder decir 'foreach (string s en myArrayList)' y hacer la conversión explícita hecha automáticamente. –

3

Cuando usa Enum.GetValues(), devuelve los valores subyacentes. Cuando usa foreach(Type...), realiza un lanzamiento al tipo enum. Por lo tanto, aunque no sean el mismo Enum, tienen los mismos valores subyacentes que no tienen problemas para emitir.

Qué está pasando en más o menos equivalente a este

int value = Enum.GetValues(typeof(Enum2))[1]; // this isn't valid code, it's more simplified 
Enum1 casted = (Enum1)value; 
8

Debido a que los valores de las enumeraciones son implícitamente enteros:

public enum Enum1 
{ 
    ONE = 0, 
    TWO = 1 
} 

public enum Enum2 
{ 
    A = 0, 
    B = 1 
} 

Los valores de Enum1 se convierten implícitamente a números enteros y luego a los valores de Enum2. Si redefinido Enum1 de la siguiente manera ...

public enum Enum1 
{ 
    ONE = 0, 
    TWO = 1, 
    THREE = 2, 
} 

... entonces sería fallar no volver "A, B", porque no hay ningún valor en Enum2 para el valor entero 2

+1

Los valores de Enum comienzan en 0, y en realidad eso imprime 'A, B, 2' en lugar de fallar - ver [Casting ints a enumeraciones en C#] (http://stackoverflow.com/questions/1758321/casting-ints-to-enums-in-c-sharp) – Justin

+0

@Justin corregido, gracias. –

1
No

es un modelo implícito aquí de Enum1 -> int e int -> Enum2.

0

La razón de esto es que las enumeraciones son moldeables implícitamente a System.Int (suponiendo que son int enums, que son por defecto).

Su segundo foreach está emitiendo explícitamente los resultados de Enum.GetValues(typeof(Enum1)) a Enum2.

2

Enum.GetValues(typeof(Enum1)) retorno {0,1} y foreach a enumerar en este rango

1

Conjeturaría alguien como Jon Skeet podría entrar aquí y completamente explicar lo que está pasando mejor que yo, pero este código:

foreach (Enum2 e in Enum.GetValues(typeof(Enum1))) 
{ 
    Console.WriteLine(e); 
} 

... está viendo todos sus valores de Enum1 como tipos.

Dado que el tipo de datos enum es como el tipo de datos int, sus valores numéricos de Enum1 se utilizan para indexar Enum2.

Cuestiones relacionadas