2013-02-19 8 views
21

Jest:Dlaczego przełącznik enum akceptuje niejawną konwersję na 0, ale nie dla żadnej innej liczby całkowitej?

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

Teraz kompilator pozwala mi napisać:

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

0 jest uważany SomeItems.A. Ale nie mogę napisać:

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

Dlaczego istnieje tylko niejawna konwersja dla 0?

+2

Zobacz odpowiedź Eric Lipperta na podobne pytanie: http: // stackoverflow.com/a/14238286/414076 –

Odpowiedz

16

od ECMA-334 (C# Language Specification)

13.1.3 to konwersja wyliczenie

Pośrednia konwersja umożliwia wyliczenie dziesiętną, liczbami całkowitymi od 0 do dosłownym być przekształcone do każdego typu wyliczeniowego.

enum's wartość domyślna to 0 i w czasie kompilacji jest znana, dlatego też jest dozwolona w instrukcji switch. W przypadku wartości innej niż 0 nie można określić podczas kompilacji, czy ta wartość będzie istnieć w wyliczeniu, czy też nie.

enum (C# Reference)

Przydzielanie dodatkowych wartości nowe wersje teksty stałe lub zmianę wartości członków enum w nowej wersji, może powodować problemy dla kodu źródłowego zależnej. Często zdarza się, że wartości wyliczenia są używane w instrukcjach przełączania, a jeśli dodano dodatkowe elementy do typu wyliczeniowego, test dla wartości domyślnych może nieoczekiwanie zwrócić wartość true .

+1

Czy znalazłeś jakieś wyjaśnienie, dlaczego tak jest? –

+0

@yBee, myślę, że to dlatego, że domyślną wartością enum jest '0' będącą typem wartości opartym na liczbie całkowitej. – Habib

+0

Teraz mogę sobie wyobrazić, że jeśli stworzymy np. "struct" lub "class" pola są inicjalizowane. Więc jeśli istnieje pole typu wyliczeniowego, jego wartość wynosi "0", nawet jeśli nie ma takiego elementu w tym wyliczeniu. Tak więc pole jest w stanie "unieruchomionym", ale nadal jest prawidłowe. Dlatego powinniśmy zawsze używać 'default' etykiety w przełączniku, nawet jeśli mamy bardzo proste i niezmienne wyliczanie. –

2

Chciałbym również dodać, że składnia z 0 zamiast dokładna enum w rachunku switch mogą stać się podatne na błędy. Rozważmy następujący kod:

enum TestEnum 
{ 
    NA = 0, 
    A 
} 

a następnie

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

To kompiluje i działa dobrze. Jeśli jednak z jakiegoś powodu, enum deklaracja zmienia się

enum TestEnum 
{ 
    NA = 1, 
    A 
} 

wszystko będzie złamane.

Chociaż w większości sytuacji domyślną wartością dla enum jest 0 i z tego powodu ta składnia może mieć miejsce, użyłbym dokładnie enum.

+1

Zabawne jest to, że nawet jeśli zmienię "A" na "3", tak że nie ma "0" w 'SomeEnum', nadal mogę napisać' SomeEumum x = 0' i złap etykietę 'case 0:' w przełączniku. –

+0

@ yBee Przeczytaj drugą odpowiedź, zawsze istnieje wartość 0 dla wyliczenia, jest to domyślna wartość dla typu wyliczeniowego zdefiniowanego w specyfikacji językowej. –

+0

@yBądź świetny sygnał ... Nawet nie zdawałem sobie z tego sprawy. Jeśli chodzi o mnie, to uniknęłabym robienia takich rzeczy z 'wyliczeniem' – horgh

Powiązane problemy