27

There is an:

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

Now compiler allows me to write:

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

0 is considered SomeItems.A. But I can't write:

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

Why only implicit conversion exists for 0?

Ryszard Dżegan
  • 24,366
  • 6
  • 38
  • 56

2 Answers2

20

From ECMA-334 (C# Language Specification)

13.1.3 Implicit enumeration conversions

An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any enum-type.

enum's default value is 0 and at compile time it is known that is why it is allowed in the switch statement. For value other than 0, it can't be determine at compile time whether this value will exist in the enum or not.

enum (C# Reference)

Assigning additional values new versions of enums, or changing the values of the enum members in a new version, can cause problems for dependant source code. It is often the case that enum values are used in switch statements, and if additional elements have been added to the enum type, the test for default values can return true unexpectedly.

Habib
  • 219,104
  • 29
  • 407
  • 436
  • 1
    Have you found any explanation why it is so? – Ryszard Dżegan Feb 19 '13 at 06:24
  • @yBee, I think its because enum's default value is `0` being an integer based value type. – Habib Feb 19 '13 at 06:29
  • Now I can imagine that if we create e.g. a `struct` or a `class` the fields are initialized. So if there is a field of enum type, its value is `0` even if there is no such item in that enum. So the field is in _cunfused_ state, but still valid. That's why we should always use `default` label in switch even if we have very simple and immutable enum. – Ryszard Dżegan Feb 19 '13 at 06:30
4

I would also add, that the syntax with 0 instead of the exact enum in the switch statement may become error prone. Consider the following code:

enum TestEnum
{
    NA = 0,
    A
}

and then

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

This compiles and works well. However if for some reason, enum declaration changes to

enum TestEnum
{
    NA = 1,
    A
}

everything will get broken.

Though in the majority of situations the default value for enum is 0 and for that reason this syntax may take place, I would use the exact enum.

horgh
  • 17,918
  • 22
  • 68
  • 123
  • 1
    The funny thing is, that even if I'll change `A` to `3` so that there is no `0` in `SomeEnum`, I can still write `SomeEnum x = 0` and catch `case 0:` label in switch. – Ryszard Dżegan Feb 19 '13 at 06:12
  • @yBee Read the other answer, there is always a 0 value for an enum, it is the default value for the enum type defined in the language spec. – Preston Guillot Feb 19 '13 at 06:15
  • @yBee great notice...I even didn't realize that. As for me, I'd also avoid doing such things with `enums` – horgh Feb 19 '13 at 06:15
  • And also `SomeEnum x = 0; var name = Enum.GetName(typeof (SomeEnum), x);` The name is `null` as can be expected. So we've got `0` as valid value if it is defined in `SomeEnum` or `0` as `null` otherwise... – Ryszard Dżegan Feb 19 '13 at 06:16