2013-02-19 6 views
21

C'è un:Perché passare a enum accetta la conversione implicita a 0 ma non per nessun altro intero?

enum SomeEnum 
{ 
    A = 0, 
    B = 1, 
    C = 2 
} 

Ora compilatore mi permette di scrivere:

SomeEnum x = SomeEnum.A; 
switch(x) 
{ 
    case 0: // <--- Considered SomeEnum.A 
     break; 
    case SomeEnum.B: 
     break; 
    case SomeEnum.C: 
     break; 
    default: 
     break; 
} 

0 è considerato SomeItems.A. Ma non posso scrivere:

SomeEnum x = SomeEnum.A; 
switch(x) 
{ 
    case 0: 
     break; 
    case 1: // <--- Here is a compilation error. 
     break; 
    case SomeEnum.C: 
     break; 
    default: 
     break; 
} 

Perché esiste solo la conversione implicita per 0?

+2

Vedere la risposta di Eric Lippert a una domanda simile: http: // StackOverflow.it/a/14238286/414076 –

risposta

16

partire ECMA-334 (C# Language Specification)

13.1.3 conversioni enumerazione implicita

una conversione enumerazione implicita permette decimale integer letterale 0 da convertire in qualsiasi enum-tipo.

enum's valore predefinito è 0 e al momento della compilazione si sa che è per questo che è ammesso nel switch. Per un valore diverso da 0, non è possibile determinare in fase di compilazione se questo valore sarà presente nell'enumerazione o meno.

enum (C# Reference)

Assegnazione di ulteriori valori di nuove versioni enumerazioni, o cambiando i valori dei membri enum in una nuova versione, può causare problemi per codice sorgente dipendente. Spesso i valori di enumerazione sono utilizzati nelle istruzioni switch e se sono stati aggiunti elementi aggiuntivi al tipo enum, il test per i valori predefiniti può restituire in modo imprevisto true.

+1

Hai trovato qualche spiegazione sul perché sia ​​così? –

+0

@yBee, penso proprio perché il valore predefinito di enum è '0' essendo un tipo di valore basato su un numero intero. – Habib

+0

Ora posso immaginare che se creiamo per es. una 'struct' o una' class' i campi sono inizializzati. Quindi, se esiste un campo di tipo enum, il suo valore è '0' anche se non vi è alcun elemento in quell'enumerazione. Quindi il campo è nello stato _cunfused_, ma ancora valido. Ecco perché dovremmo sempre usare l'etichetta 'default' in switch anche se abbiamo enum molto semplice e immutabile. –

2

Vorrei anche aggiungere, che la sintassi con 0 invece l'esatto enum nella dichiarazione switch possono diventare soggetto a errori. Si consideri il seguente codice:

enum TestEnum 
{ 
    NA = 0, 
    A 
} 

e poi

var e = TestEnum.NA; 
switch(e) 
{ 
    case 0: 
     { 
      break; 
     } 
    case TestEnum.A: 
     { 
      break; 
     } 
} 

Questo compila e funziona bene. Tuttavia, se per qualche motivo, enum dichiarazione cambia in

enum TestEnum 
{ 
    NA = 1, 
    A 
} 

tutto andrà rotto.

Anche se nella maggior parte delle situazioni il valore predefinito per enum è 0 e per questo motivo questa sintassi può avvenire, vorrei utilizzare l'esatto enum.

+1

La cosa divertente è che, anche se cambierò 'A' in' 3' in modo che non ci sia '0' in' SomeEnum', posso ancora scrivere 'SomeEnum x = 0' e catch 'case 0:' label in switch. –

+0

@yBee Leggi l'altra risposta, c'è sempre un valore 0 per un enum, è il valore predefinito per il tipo enum definito nelle specifiche della lingua. –

+0

@yBee grande preavviso ... non me ne sono nemmeno reso conto. Per quanto mi riguarda, eviterei anche di fare cose simili con 'enums' – horgh