2013-02-19 7 views
21

Es gibt ein:Warum wechseln für enum akzeptiert implizite Konvertierung in 0, aber keine für andere Ganzzahl?

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

Jetzt Compiler ermöglicht es mir zu schreiben:

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

0SomeItems.A betrachtet. Aber ich kann nicht schreiben:

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

Warum nur implizite Konvertierung für 0 existiert?

+2

Siehe Eric Lipperts Antwort auf eine ähnliche Frage: http: // stackoverflow.com/a/14238286/414076 –

Antwort

16

Von ECMA-334 (C# Language Specification)

13.1.3 Implicit Enumeration Konvertierungen

Eine implizite Enumeration Umwandlung erlaubt die dezimale ganzzahlige-Literal 0 irgendeinen enum-Typen umgewandelt werden.

enum's Standardwert ist 0 und bei der Kompilierung ist es bekannt, deshalb ist es in der switch-Anweisung erlaubt. Für einen anderen Wert als 0 kann zur Kompilierzeit nicht bestimmt werden, ob dieser Wert in der Enumeration vorhanden ist oder nicht.

enum (C# Reference)

Zuordnung zusätzliche Werte neue Versionen von Aufzählungen oder die Werte der Enum-Mitglieder in einer neuen Version zu ändern, kann für abhängig Quellcode zu Problemen führen. Es ist oft der Fall, dass Enum-Werte in Switch-Anweisungen verwendet werden, und wenn zusätzliche Elemente zum Enum-Typ hinzugefügt wurden, kann der Test für Standardwerte unerwartet zurückgeben.

+1

Haben Sie eine Erklärung gefunden, warum es so ist? –

+0

@yBee, ich denke es ist, weil Enum den Standardwert '0' ist ein ganzzahliger Werttyp. – Habib

+0

Jetzt kann ich mir vorstellen, dass wenn wir z. eine 'struct' oder eine' class' die Felder werden initialisiert. Wenn es also ein Feld vom Aufzählungstyp gibt, ist sein Wert "0", selbst wenn es in dieser Aufzählung kein solches Element gibt. Das Feld befindet sich also im _cunfused_-Zustand, ist aber immer noch gültig. Deshalb sollten wir immer 'default' label in switch verwenden, auch wenn wir eine sehr einfache und unveränderliche enum haben. –

2

Ich möchte auch hinzufügen, dass die Syntax mit 0 statt die genaue enum in der switch Anweisung fehleranfällig werden kann. Betrachten Sie den folgenden Code ein:

enum TestEnum 
{ 
    NA = 0, 
    A 
} 

und dann

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

Dies kompiliert und funktioniert gut. Wenn jedoch aus irgendeinem Grund enum Erklärung Änderungen an

enum TestEnum 
{ 
    NA = 1, 
    A 
} 

alles wird kaputt gehen.

Obwohl in den meisten Situationen der Standardwert für enum ist 0 und aus diesem Grund kann diese Syntax stattfinden, würde ich die genaue enum verwenden.

+1

Die lustige Sache ist, dass, selbst wenn ich 'A' zu' 3' ändern werde, so dass es keine '0' in' SomeEnum' gibt, kann ich 'SomeEnum x = 0' schreiben und catch 'case 0:' Label im Schalter. –

+0

@yBee Lesen Sie die andere Antwort, es gibt immer einen Wert 0 für eine Enumeration, es ist der Standardwert für den in der Sprachspezifikation definierten Aufzählungstyp. –

+0

@yBee tolle Nachricht ... Ich habe das gar nicht bemerkt. Was mich betrifft, würde ich auch vermeiden, solche Dinge mit 'enums' zu tun. – horgh

Verwandte Themen