2012-02-17 6 views
6

Dato questo codice:Enum.GetValues ​​(typeof (....)) non restituendo il corretto enum valori

public enum Enum1 
{ 
    ONE, 
    TWO 
} 

public enum Enum2 
{ 
    A, 
    B 
} 

Questo codice restituisce ONE, TWO:

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

Ma questo codice, invece di fallire (perché Enum2 e viene utilizzato con typeof(Enum1)), restituisce A, B:

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

perché?

risposta

9

Perché sotto le copertine Enum sono solo int - il secondo restituisce i valori di Enum1, ma in realtà quei valori sono solo 0 e 1. Quando lanci quei valori al tipo Enum2 questi sono ancora validi e corrispondono ai valori "A" e "B".

+1

Ovviamente lo fanno ... Sciocco! Ho dimenticato che le enumerazioni in C# sono in realtà di fantasia.Ero più abituato alle enumerazioni di Java che sono classi a pieno titolo. Triste che il compilatore non lo cattura però ... – JohnDoDo

+6

@JohnDoDo: Il compilatore non lo cattura perché "foreach (Enum2 e ..." esegue una ** conversione ** esplicita - un cast, in modo efficace - da il tipo di raccolta al tipo di variabile loop. È legale per * cast * '(Enum2) enum1', quindi è legale fare implicitamente la stessa cosa con un * foreach *. Ricorda, foreach è stato inventato prima dei generici; aveva una ArrayList di stringhe, dovresti essere in grado di dire 'foreach (stringa s in myArrayList)' e fare automaticamente la conversione esplicita. –

3

Quando si utilizza Enum.GetValues() restituisce i valori sottostanti. Quando si utilizza foreach(Type...) esegue un cast per il tipo enum. Quindi, mentre potrebbero non essere lo stesso Enum, hanno gli stessi valori di fondo che non hanno problemi a lanciare.

Quello che sta accadendo in meno equivalente a questo

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

Poiché i valori delle enumerazioni sono implicitamente interi:

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

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

I valori di Enum1 vengono implicitamente convertiti in numeri interi e poi ai valori di Enum2. Se ridefinito Enum1 come segue ...

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

... allora sarebbe sicuro non ritorno "A, B", perché non v'è alcun valore nel Enum2 per il valore intero 2

+1

I valori di enum partono da 0, e in realtà stampa 'A, B, 2' invece di fallire - vedi [Casting ints to enums in C#] (http://stackoverflow.com/questions/1758321/casting-ints-to-enums-in-c-sharp) – Justin

+0

@Justin risolto, grazie. –

1

Ci è un cast implicito qui da Enum1 -> int e int -> Enum2.

0

La ragione di ciò è che le enumerazioni sono implicitamente applicabili a System.Int (supponendo che siano int enum, che sono per impostazione predefinita).

Il secondo foreach sta quindi trasmettendo esplicitamente i risultati di Enum.GetValues(typeof(Enum1)) a Enum2.

2

Enum.GetValues(typeof(Enum1)) ritorno {0,1} e foreach si elencare in questa fascia

1

direi qualcuno come Jon Skeet potrebbe venire qui e completamente spiegare cosa sta succedendo meglio di me, ma questo codice:

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

... sta visualizzando tutti i valori Enum1 come tipi Enum2.

Poiché il tipo di dati enum è come il tipo di dati int, i valori numerici da Enum1 vengono utilizzati per indicizzare Enum2.