自定义枚举

自定义枚举在结构上是基于 int 类型的,它们的使用原则与上一节嵌入式枚举中介绍的原则完全一致。因此,本节我们介绍的是自定义枚举,严格来说,它们不属于嵌入式。

可使用 enum 关键字在 MQL5 代码中描述自定义枚举。最简单的说明形式如下:

enum name
{
  element1,
  element2,
  element3
};

该说明在程序中注册了一个命名为 name 的枚举类型,各元素用花括号括起来并用逗号分隔(元素数量只取决于 int 的最大值,在实际任务中可以认为没有上限)。随后,标识符 element1element2element3 便可以在程序中定义了这些标识符的上下文中使用:全局(即在所有函数外部)或函数内部(参见 上下文、可见性和变量生命周期一节)。

请注意右花括号后面的分号。这个分号是必需的,因为枚举说明是一个独立语句,任何 MQL5 语句之后必须有分号。

默认情况下,标识符取常量值,从 0 开始,依次递增 1。如有必要,程序员可以在标识符右边使用 '=' 符号为每个元素定义特定值。例如,上文中的语句与以下语句等效:

enum name
{
  element1 = 0,
  element2 = 1,
  element3 = 2
};

指定的值必须是常量或者是编译器在编译阶段可以计算的表达式(更多详细信息,请参见以下示例)。

如果没有为所有元素定义值,则会自动计算跳过的值,计算方法是将最近的(前面的)已知值自动加 1。例如,

enum name
{
  element1 = 1,
  element2,
  element3 = 10,
  element4,
  element5
};

这里,前两个元素取值 1 和 2(计算得出),从第三个元素开始取值 10(显式赋值)、11 和 12(后两个用 10 自动加 1 计算得出)。

TypeUserEnum.mq5 脚本中提供了一些描述自定义枚举的例子。

const int zero = 0// runtime value is not known at compile time
 
enum
{
  MILLION = 1000000
};
 
enum RISK
{
  // OFF      = zero, // error: constant expression required
  LOW      = -1,
  MODERATE = -2,
  HIGH     = -3,
};
 
enum INCOME
{
  LOW      = 1,
  MODERATE = 2,
  HIGH     = 3,
  ENORMOUS = MILLION,
};
 
void OnStart()
{
  enum INTERNAL
  {
    ON,
    OFF,
  };
 
  // int x = LOW; // ambiguous access, can be one of
  int x = RISK::LOW;
  int y = INCOME::LOW;
}

INTERNAL 枚举展示了在函数内部描述自定义枚举的可能性,通过这种描述,可以限定该类型的可见/可用域,这在处理名称冲突方面很有用。

RISK 枚举表明元素可被赋予负值。无法描述注释元素 OFF,原因是尝试用一个非常量表达式来初始化此元素:在这种情况下,指定了 zero 变量,但编译器无法计算出此变量的值。

在 INCOME 枚举中,用上文定义的其他枚举的 MILLION 元素的值成功初始化了 ENORMOUS 元素。枚举是在编译时创建的,因此它们在初始化表达式中是可用的。

包含 MILLION 的枚举没有名称,这样的枚举称为匿名枚举。它们的基本用途是声明常量。而命名枚举则更多地用于声明常量,因为它们允许根据元素的含义对元素进行分组。

示例中定义了 2 个枚举类型,它们的元素具有相同名称,因此在声明 x 变量时指定 LOW 标识符会导致编译错误“访问权限不明确”,因为未明确说明是哪个元素的枚举。请注意,标识符可能有不同的值(在本例中就是这样)。

为了解决这个问题,提供了一个特殊的上下文运算符:两个冒号 "::"。它们有助于形成语言元素(即枚举元素)的完整标识符,在我们的例子中:首先,指定枚举名称,然后是运算符 "::",最后是元素标识符。示例:RISK::LOW 和 INCOME::LOW。我们将在相关章节中了解所有运算符。