Перечисления и константы. Что использовать, когда?

97

Я читал перечисления и нашел их очень похожими на объявление констант. Как мне узнать, когда использовать константу, а не перечисление, или наоборот. Какие преимущества использования перечислений?

Драко
источник
см. также stackoverflow.com/questions/755685/c-static-readonly-vs-const
Джон Хенкель
см. также stackoverflow.com/questions/11575376/… для аналогичного вопроса для Java (ответы в основном относятся и к C #).
Алексей Левенков

Ответы:

97

Используйте перечисления, если вы хотите определить диапазон значений, которым может быть что-то. Цвет - очевидный пример:

public enum Colour
{
    White,
    Red,
    Blue
}

Или, может быть, набор возможных вещей вроде: (Пример, который я украл отсюда, поскольку я ленив)

[FlagsAttribute]
enum DistributedChannel
{
  None = 0,
  Transacted = 1,
  Queued = 2,
  Encrypted = 4,
  Persisted = 16,
  FaultTolerant = Transacted | Queued | Persisted
}

Константы должны быть для одного значения, например PI. Нет диапазона значений PI, есть только PI.

Другие моменты, которые следует учитывать:

  • a: Константы не обязательно указывают на связь между константами, тогда как перечисление указывает, что что-то может быть одним из набора, определенного перечислением.
  • b: определенное перечисление может помочь вам с проверкой типа при использовании в качестве аргумента. Константы - это просто значения, поэтому они не предоставляют никакой дополнительной семантической информации.
Эндрю Барретт
источник
1
Что, если вы в конечном итоге будете использовать .ToString()в перечислении много, любое значение при использовании класса с константными строками, который выглядит и действует как перечисление, но обходит вызов ToString()? Пример
Sinjai
Подождите, думаю, я ответил на свой вопрос. Код в этом примере не будет работать: вам придется принимать ввод как строку, которая на самом деле не будет вести себя как перечисление.
Sinjai
1
Почему бы вам просто не иметь статический класс Color с постоянными цветами, а не enum? Какая разница?
WDUK
вкратце заявлениеType Safety"
ahmednabil88
31

В других ответах не хватает того, что перечисления имеют целочисленный базовый тип. Вы можете изменить значение по умолчанию с int на любой другой интегральный тип, кроме char, например:

enum LongEnum : long {
    foo,
    bar,
}

Вы можете явно и неявно привести к базовому типу, что полезно в операторах switch. Помните, что любое значение базового типа можно привести к перечислению, даже если перечисление не имеет члена с соответствующим значением. Поэтому использование всегда раздела по умолчанию в переключателе - хорошая идея. Кстати, .NET допускает даже перечисления с плавающей запятой, но вы не можете определить их в C #, хотя я думаю, что вы все еще можете их использовать (кроме switch).

Кроме того, использование перечислений обеспечивает большую безопасность типов. Если вы намереваетесь использовать, например, константы int в качестве параметров метода, я мог бы вызвать метод с любым значением int. Конечно, с помощью приведения это может происходить и с перечислениями, но это не произойдет случайно. Хуже того, возможность перепутать порядок параметров.

void method(int a, int b) {...}

Если только константа A может входить в a, а константа B только может входить в b, то использование двух разных типов перечислений обнаружит любое неправильное использование во время компиляции.

Йоханнес
источник
21

Константа - это языковая функция, которая говорит, что переменная не изменяет значение (поэтому компилятор может выполнять оптимизацию на основе этих знаний), где перечисление - это определенный тип.

Константы могут быть любого типа данных, но перечисление - это перечисление.

Я использую перечисление в любом месте, где у вас может быть несколько вариантов и вы хотите улучшить читаемость кода. т.е. у вас могут быть уровни трассировки как int со значениями 0, 1, 2 или как перечисление как error, warning и info.

Enum также могут использоваться как побитовые операторы, например FontStyle.Bold | FontStyle.Italic даст вам полужирный и курсивный шрифт.

Роберт Маклин
источник
8

В дополнение к ответу Роберта:

  1. Используйте enum для конечного набора именованных значений. На самом деле вас не волнует числовое значение каждого символа (но у вас все еще есть возможность наложить их, например, для совместимости с устаревшей системой).

  2. Роберт: Да, Enum можно использовать как битовые поля. Используйте атрибут Flags (и убедитесь, что члены перечисления имеют подходящие числовые значения).

Серж Вотье
источник
3

Константа AC # похожа на переменную в том, что она дает определенное имя для значения. Однако константа отличается от стандартной переменной, потому что однажды определенное значение, присвоенное константе, никогда не может быть изменено. Основным преимуществом констант является их помощь в создании самодокументируемого кода, а также возможность декларирования ключевых значений в одном месте, что упрощает обслуживание в случае необходимости обновления значения и повторной компиляции программного обеспечения.

В то время как списки перечислителя полезны для определения последовательностей и состояний, особенно когда есть естественное прохождение через эти состояния. Это связано с тем, что каждую константу в списке можно отформатировать и сравнить, используя ее имя или значение. Перечисление также можно использовать для определения ограниченного набора допустимых значений.

просто резкий
источник
3

Одна вещь, которую я нахожу удобной при использовании enumвместо, const- это то, что вы можете перебирать значения в файле enum, это намного сложнее сделать со constзначениями.

Дэвид Клемпфнер
источник