Перечисляемые типы относятся к значимым типам.Перечисление (Enumeration) – это определяемый пользователем целочисленный тип, который позволяет специфицировать набор допустимых значений, и назначить каждому понятное имя.
Объявляются перечисляемые типы с помощью ключевого слова enum. Формат определения такой:
enum [имя_перечисления] { [имя1], [имя2], … };
Имя задает имя перечисляемого типа, а список перечисления представляет собой список идентификаторов, разделенных запятыми.
Доступ к членам перечисления осуществляется с помощью имени перечисляемого типа и оператора точка.
public enum BorderSide { Left, Right, Top, Bottom } BorderSide topSide = BorderSide.Top; bool isTop = (topSide == BorderSide.Top); // true
Каждый член перечисления указывает на целочисленное значение. По умолчанию эти значения имеют тип int и членам перечисления присваиваются константы 0, 1, 2, … (т.е. целые числа начиная с нуля). Однако для членов перечисления можно задать и другой целочисленный
тип: public enum BorderSide : byte { Left,Right,Top,Bottom }
Также можно явно задать целочисленные значения для каждого члена:
public enum BorderSide : byte { Left=1, Right=2, Top=10, Bottom=11 }
Можно задать только некоторые члены перечисления, при этом члены, которым не заданы значения, будут увеличиваться на один с последнего заданного члена:
public enum BorderSide : byte { Left=1, Right, Top=10, Bottom }
Значение перечисления можно представить тремя способами:
Константу перечисления можно использовать везде, где допустимо целочисленное значение. Однако между типом enum и встроенным целочисленным типом неявные преобразования невозможны, поэтому при необходимости должно использоваться явное приведение типов.
int i = (int) BorderSide.Left; // Приведение перечисления к значимому типу
BorderSide side = (BorderSide) i; // Приведение значения к типу перечисления
bool leftOrRight = (int) side <= 2; // Приведение перечисления к значимому типу
Также можно явно приводить один тип перечисления к другому, при этом преобразование осуществляется через целочисленные значения перечисления.
HorizontalAlignment h = (HorizontalAlignment) BorderSide.Right; // Эквивалентно: HorizontalAlignment h = (HorizontalAlignment) (int) BorderSide.Right;
Литерал 0 обрабатывается особо: он не требует явного приведения:
BorderSide b = 0; // Не требуется явного приведения if (b == 0) ...
Экземпляру перечисления можно присвоить значение, которое выходит за пределы значений его членов:
BorderSide b = (BorderSide) 12345; Console.WriteLine (b); // 12345
Члены перечислений можно комбинировать (объединять). Чтобы избежать неоднозначности членам комбинируемых перечислений необходимо явно присваивать значения.
[Flags] public enum BorderSides { None=0, Left=1, Right=2, Top=4, Bottom=8 }
Комбинировать значения перечислений можно с помощью побитовых операторов, таких как | и &.
BorderSides leftRight = BorderSides.Left | BorderSides.Right; if ((leftRight & BorderSides.Left) != 0) Console.WriteLine ("Includes Left"); // Includes Left string formatted = leftRight.ToString(); // "Left, Right" BorderSides s = BorderSides.Left; s |= BorderSides.Right; Console.WriteLine (s == leftRight); // True
По соглашению комбинированным членам перечисления дается множественное имя, например leftRight.
Комбинированным перечислениям следует присваивать атрибут Flags. Если этого не сделать метод ToString будет возвращать числовые значения, а не последовательность имен. Перечисления с атрибутом flags называются битовыми флагами.
Сочетания членов можно указывать внутри самих перечисляемых типов: [Flags] public enum BorderSides { None=0, Left=1, Right=2, Top=4, Bottom=8, LeftRight = Left | Right, TopBottom = Top | Bottom, All = LeftRight | TopBottom }
С перечислениями можно использовать следующие операторы:
= == != < > <= >= + - ^ & | ~+= -= ++ - sizeof
При этом перечисления воспринимаются как целочисленные значения. Сложение возможно только между типом enum и целочисленным типом, но не между двумя перечислениями.
Класс System.Enum предоставляет расширенную поддержку типов enum, обеспечивая унификацию и определяя статические служебные методы. Унификация типов enum подразумевает возможность неявного приведения любого члена перечисления к типу System.Enum. Статические методы дают возможность выполнения преобразований и получения списка членов.
Статический метод Enum.GetUnderlyingType возвращает лежащий в основе перечисления целочисленный тип:
Type integralType = Enum.GetUnderlyingType (anyEnum.GetType());
Статический метод Enum.ToObject преобразует целочисленное значение в экземпляр enum указанного типа:
object bs = Enum.ToObject (typeof (BorderSides), 3); Console.WriteLine (bs); // Left, Right
Преобразовать enum в строку можно с помощью статического метода Enum.Format либо с помощью экземплярного метода ToString. Оба метода принимают форматную строку.
Метод Enum.Parse преобразует строку в enum. Он принимает тип enum и строку, которая может включать множество членов. Необязательный третий аргумент позволяет выполнить разбор не чувствительный к регистру. Если член не найден генерируется исключение ArgumentException. BorderSides leftRight = (BorderSides) Enum.Parse (typeof (BorderSides), "Left, Right");
Метод Enum.GetValues возвращает массив, содержащий все члены указанного типа enum: foreach (Enum value in Enum.GetValues (typeof (BorderSides))) Console.WriteLine (value);
Метод Enum.GetNames делает тоже самое, но возвращает массив строк.
Для перечислений предусмотрены следующие форматные строки:
G или g — общий формат применяемый по умолчанию
F или f — рассматривает экземпляр enum как флаг, позволяя коректно преобразовывать составные члены
D или d — десятичное значение, извлекает лежащее в основе целочисленное значение и представляет его в виде строки
X или x — шестнадцатеричное значение, извлекает лежащее в основе целочисленное значение и представляет его в виде шестнадцатеричной записи
Итак,
Например, создадим перечисление Directions, которое будет соответствовать направлениям движения:
enum Directions { Left, Right, Forward, Back };
Объявив таким образом перечисление, каждой символически обозначаемой константе присваивается целочисленное значение, начиная с 0 (Left = 0, Right = 1 …). Это целочисленное значение можно задавать и самому:
enum Directions { Left, Right = 5, Forward = 10, Back };
Back в этом примере будет иметь значение 11.Пример программы с использованием перечисления: