Назад Вперед Содержание

Перечисление (enumeration)

Перечисляемые типы относятся к значимым типам.Перечисление (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 }

Значение перечисления можно представить тремя способами:

  1. как тип enum
  2. как лежащее в основе целочисленное значение
  3. как строку
Значения перечислений могут преобразовываться между этими типами.

Приведение перечислений

Константу перечисления можно использовать везде, где допустимо целочисленное значение. Однако между типом 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 Enums)

Члены перечислений можно комбинировать (объединять). Чтобы избежать неоднозначности членам комбинируемых перечислений необходимо явно присваивать значения.

[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

Класс 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 — шестнадцатеричное значение, извлекает лежащее в основе целочисленное значение и представляет его в виде шестнадцатеричной записи

Итак,

  1. Как и другие классы, перечисления могут быть объявлены непосредственно в пространстве имен проекта или могут быть вложены в описание класса. Последний вариант часто применяется, когда перечисление используется в интересах одного класса. В этом случае оно может иметь модификатор доступа private.
  2. Константы разных перечислений могут совпадать, как в перечислениях MyColors и TwoColors. Имя константы всегда уточняется именем перечисления.
  3. Константы могут задаваться словами русского языка.
  4. Разрешается задавать базовый класс перечисления. Для перечисления Sex базовым классом является byte, а для перечисления Days - класс long.
  5. Разрешается не только задавать базовый класс, но и указывать начальный элемент подмножества, на которое проецируется множество значений перечисления. public enum Sex: byte {man=1, woman}; public enum Days:long {Sun,Mon,Tue,Wed,Thu, Fri, Sat}; Для перечисления Sex в качестве базового класса выбран класс byte, а подмножество значений начинается с 1, так что хранимым значением константы man является 1, а woman - 2.

Пример

Например, создадим перечисление Directions, которое будет соответствовать направлениям движения:

enum Directions { Left, Right, Forward, Back };

Объявив таким образом перечисление, каждой символически обозначаемой константе присваивается целочисленное значение, начиная с 0 (Left = 0, Right = 1 …). Это целочисленное значение можно задавать и самому:

enum Directions { Left, Right = 5, Forward = 10, Back };

Back в этом примере будет иметь значение 11.Пример программы с использованием перечисления:

Отработка

Назад Вперед Содержание