Чего не хватает в других ответах, так это того, что перечисления имеют целочисленный базовый тип. Вы можете изменить значение по умолчанию с int на любой другой целочисленный тип, кроме char, например:
enum LongEnum : long {
foo,
bar,
}
Вы можете явно и неявно приводить к базовому типу, что полезно в операторах переключения. Помните, что в перечисление можно привести любое значение базового типа, даже если перечисление не имеет члена с соответствующим значением. Поэтому всегда рекомендуется использовать секцию по умолчанию в коммутаторе. Кстати, сама .NET допускает даже перечисления с плавающей запятой, но вы не можете определить их в C #, хотя я думаю, что вы все равно можете их использовать (кроме как в switch).
Кроме того, использование перечислений дает вам больше безопасности типов. Если вы собираетесь использовать, например, константы int как параметры метода, тогда я мог бы вызвать метод с любым значением int. Конечно, через приведение типов это может произойти и с перечислениями, но это не произойдет случайно. Хуже возможность запутать порядок параметров.
void method(int a, int b) {...}
Если только константа A может входить в a, а константа B может входить только в b, то использование двух различных типов перечислений позволит обнаружить любое неправильное использование во время компиляции.