Перечисления

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

Например, перечисление ENUM_DAY_OF_WEEK содержит константы для всех дней недели:

Идентификатор

Описание

Значение

SUNDAY

Воскресенье

0

MONDAY

Понедельник

1

TUESDAY

Вторник

2

WEDNESDAY

Среда

3

THURSDAY

Четверг

4

FRIDAY

Пятница

5

SATURDAY

Суббота

6

А перечисление ENUM_ORDER_TYPE описывает все поддерживаемые типы ордеров в MetaTrader 5:

Идентификатор

Описание

Значение

ORDER_TYPE_BUY

Рыночный ордер на покупку

0

ORDER_TYPE_SELL

Рыночный ордер на продажу

1

ORDER_TYPE_BUY_LIMIT

Отложенный ордер Buy Limit

2

ORDER_TYPE_SELL_LIMIT

Отложенный ордер Sell Limit

3

ORDER_TYPE_BUY_STOP

Отложенный ордер Buy Stop

4

ORDER_TYPE_SELL_STOP

Отложенный ордер Sell Stop

5

ORDER_TYPE_BUY_STOP_LIMIT

По достижении цены ордера выставляется отложенный ордер Buy Limit по цене StopLimit

6

ORDER_TYPE_SELL_STOP_LIMIT

По достижении цены ордера выставляется отложенный ордер Sell Limit по цене StopLimit

7

ORDER_TYPE_CLOSE_BY

Ордер на закрытие позиции встречной позицией

8

Всего имеется несколько десятков разных перечислений. Их названия начинаются с префикса "ENUM_". Мы будем изучать их по мере продвижения по соответствующим предметным областям.

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

Компилятор следит за тем, чтобы значением перечисления всегда была одна из предопределенных констант. В противном случае возникнет предупреждение или ошибка компиляции (в зависимости от контекста, см. пример).

Вот как выглядит "внутри" перечисление ENUM_DAY_OF_WEEK (скрипт MQL5/Scripts/MQL5Book/p2/TypeEnum.mq5).

void OnStart()
{
  ENUM_DAY_OF_WEEK sun = SUNDAY;     // sun = 0
  ENUM_DAY_OF_WEEK mon = MONDAY;     // mon = 1
  ENUM_DAY_OF_WEEK tue = TUESDAY;    // tue = 2
  ENUM_DAY_OF_WEEK wed = WEDNESDAY;  // wed = 3
  ENUM_DAY_OF_WEEK thu = THURSDAY;   // thu = 4
  ENUM_DAY_OF_WEEK fri = FRIDAY;     // fri = 5
  ENUM_DAY_OF_WEEK sat = SATURDAY;   // sat = 6
  
  int i = 0;
  ENUM_DAY_OF_WEEK x = i// warning: implicit enum conversion
  ENUM_DAY_OF_WEEK y = 1// ok, equals to MONDAY
  ENUM_ORDER_TYPE buy = ORDER_TYPE_BUY;   // buy = 0
  ENUM_ORDER_TYPE sell = ORDER_TYPE_SELL// sell = 1
  // ...
  
  // warning: implicit conversion
  //          from 'enum ENUM_DAY_OF_WEEK' to 'enum ENUM_ORDER_TYPE'
  //          'ENUM_ORDER_TYPE::ORDER_TYPE_SELL' will be used
  //          instead of 'ENUM_DAY_OF_WEEK::MONDAY'
  ENUM_ORDER_TYPE type = MONDAY;
  // compilation error: uncomment to reproduce
  // ENUM_DAY_OF_WEEK day = ORDER_TYPE_CLOSE_BY; // cannot convert enum
  // ENUM_DAY_OF_WEEK z = 10; // '10' - cannot convert enum
}

Все константы дней недели кодируются числами от 0 до 6, причем отсчет начинается с воскресенья. В принципе, константы не обязательно должны иметь последовательные номера или начинаться с 0. Существуют перечисления, где это не так.

Обратите внимание, что одни и те же константы могут означать в разных типах перечислений разные вещи. Например, для ордеров ORDER_TYPE_BUY и ORDER_TYPE_SELL в перечислении ENUM_ORDER_TYPE используются те же значения (0 и 1), что и для дней недели SUNDAY и MONDAY в перечислении ENUM_DAY_OF_WEEK.

При копировании значения из простой целочисленной переменной i в переменную перечисления x компилятор выдает предупреждение, так как на стадии выполнения программы в переменной i может оказаться величина, отличная от разрешенных констант.

В переменную y мы записываем число 1, которое соответствует MONDAY, и компилятор считает это корректной операцией.

Попытка записать константу одного перечисления в переменную другого перечисления (как MONDAY для переменной type в вышеприведенном примере) может вызвать предупреждение о неявном преобразовании одного типа в другой. Происходит это, если записываемая константа имеет такое же значение, что и один из элементов целевого перечисления. Иными словами в каждом из двух перечислений есть свой собственный элемент с соответствующим значением. Тогда компилятор делает неявное преобразование автоматически за программиста, но с помощью предупреждения просит обратить внимание и проверить, так ли все задумывалось: то, что MONDAY будет заменен на ORDER_TYPE_SELL действительно выглядит странно, но здесь мы сделали это намеренно для демонстрации.

В том случае, если копируемый элемент не совпадает по значению ни с одним элементом другого перечисления, генерируется ошибка компиляции, так как неявная конвертация невозможна (например, при записи ORDER_TYPE_CLOSE_BY в переменную day).

Закомментированная строка с переменной z также вызывает ошибку компиляции, поскольку значение 10 не принадлежит ENUM_DAY_OF_WEEK. Если программист уверен, что в каком-то экзотическом случае все же требуется записать в переменную типа перечисления произвольное значение, он может воспользоваться явным приведением типов.

О явных и неявных приведениях типов рассказывается в разделе Приведение типов.

MQL5 позволяет программисту объявлять собственные прикладные перечисления с помощью ключевого слова enum — данная возможность описана в следующем разделе Пользовательские перечисления (enum).