枚举

枚举是 MQL5 中内置的一组类型,每个枚举都包含一组命名常量来描述相关的概念或特性。这些常量也称为枚举元素。

例如,ENUM_DAY_OF_WEEK 枚举包含表示一周中所有天数的常量:

标识符 (ID)

说明

SUNDAY

星期日

0

MONDAY

星期一

1

TUESDAY

星期二

2

WEDNESDAY

星期三

3

THURSDAY

星期四

4

FRIDAY

星期五

5

SATURDAY

星期六

6

ENUM_ORDER_TYPE 枚举描述了 MetaTrader 5 中支持的所有订单类型:

标识符 (ID)

说明

ORDER_TYPE_BUY

市场买入订单

0

ORDER_TYPE_SELL

市场卖出订单

1

ORDER_TYPE_BUY_LIMIT

限价买入挂单

2

ORDER_TYPE_SELL_LIMIT

限价卖出挂单

3

ORDER_TYPE_BUY_STOP

买入止损挂单

4

ORDER_TYPE_SELL_STOP

卖出止损挂单

5

ORDER_TYPE_BUY_STOP_LIMIT

达到订单价格后,限价买入挂单会以限价止损价格成交

6

ORDER_TYPE_SELL_STOP_LIMIT

达到订单价格后,限价卖出挂单会以限价止损价格成交

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 开始。某些枚举中就不是这样。

请注意,相同常量在不同枚举类型中可能代表不同含义。例如,对于 ENUM_ORDER_TYPE 枚举中的 ORDER_TYPE_BUY 和 ORDER_TYPE_SELL 订单,ENUM_DAY_OF_WEEK 中的 SUNDAY 和 MONDAY(表示一周内的日期)具有相同的值(0 和 1)。

把简单整数变量 i 的值拷贝到枚举变量 x 时,编译器会给出一个警告,因为在程序执行阶段,变量 i 中可能包含不允许的常量值。

在变量 y中,我们获取数字 1(表示 MONDAY),编译器认为这是一个正确的操作。

如果尝试将一个枚举的常量写入另一个枚举的变量(如上例中将 MONDAY 写入 type 变量)可能会导致有关隐式类型转换的警告。如果正在写入的常量与某个目标枚举元素的值相同,就会发生这种情况。也就是说,这两个枚举各自有一个具有相关值的元素。然后,编译器代替程序员自动执行隐式转换,但会显示一个警告,提醒程序员检查是否一切正常:实际上,用 ORDER_TYPE_SELL 替代 MONDAY 确实很怪异;但为了进行演示,我们故意这么做了。

如果被拷贝的元素的值与另一个枚举的任何元素都不匹配(例如将 ORDER_TYPE_CLOSE_BY 写入 day 变量中),则会生成编译错误,因为隐式转换无法完成。

带有 z 变量的注释字符串也会导致编译错误,因为 ENUM_DAY_OF_WEEK 不包含值 10。如果程序员确信,在特殊情况下,仍然需要在枚举类型变量中获取随机值,则可以使用显式类型强制转换。

显式和隐式类型强制转换将在 类型强制转换一节中讨论。

MQL5 允许程序员使用 enum 关键字来声明自己应用的枚举。这个特性将在下一节 自定义枚举 (enum) 中说明。