一、枚举类型(Enumerated Type)
Pascal 的枚举是封装性很好的不透明类型,日常开发使用频率远高于其他语言的枚举。
基础定义写法
type
TAnimalKind = (akDuck, akCat, akDog);
约定:枚举常量名增加类型缩写双字母前缀
ak= Animal Kind(TAnimalKind 的缩写)- 作用:枚举常量默认属于单元全局命名空间,加前缀大幅降低和其他变量、类型重名冲突概率。
TAnimalKind 这里的T可以不写,只是业界规范。但是建议加上。这样一看就知道这是一个枚举。
type
AnimalKind = (akDuck, akCat, akDog); // 无 T,语法合法Code language: JavaScript (javascript)
补充说明:
- 重名不会直接编译报错,不同单元允许同名标识符;
- 但为了代码可读性、全局检索(grep)方便,推荐主动规避命名冲突。
作用域枚举(限定枚举,{$scopedenums on})
编译器指令 {$scopedenums on} 可把枚举常量隔离到类型内部,不再污染全局命名空间
默认情况不开启
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;
type TAnimalKind = (akDuck, akCat);
var k: TAnimalKind;
begin
k := akDuck; // 直接写常量,不用加 TAnimalKind.
WriteLn(k); //输出akDuck
end.Code language: PHP (php)
我们前面也说过,上面代码从begin 开始执行。

带上ak前缀更好,避免冲突,不带其实也不会错。
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;
type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
k := Duck;
WriteLn(k);//Duck
end.Code language: PHP (php)

开启 {$scopedenums on} 后必须写「类型名.」
- 访问时必须加类型名限定:
TAnimalKind.akDuck - 不再需要
ak前缀,常量可直接简写为 Duck、Cat、Dog
{$scopedenums on}
type
TAnimalKind = (Duck, Cat, Dog);
var
Kind: TAnimalKind;
begin
Kind := TAnimalKind.Duck; // 必须带类型限定
end;Code language: PHP (php)
如果不加前缀
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
{$scopedenums on}
program EnumDemo;
type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
k := Duck; // not TAnimalKind.
WriteLn(k);
end.Code language: PHP (php)
编译报错
D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
mydemo.dpr(9,8) Error: Identifier not found "Duck"
mydemo.dpr(11,4) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: C:\FPC\3.2.2\bin\i386-Win32\ppc386.exe returned an error exitcodeCode language: CSS (css)
下面加上前缀后
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
{$scopedenums on}
program EnumDemo;
type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
k := TAnimalKind.Duck; // not TAnimalKind.
WriteLn(k);
end.Code language: PHP (php)
就可以正常编译

枚举与整数强制转换
枚举属于不透明类型,不能直接和整数互相赋值,必须手动强制转换:
- 枚举 → 整数:
Ord(枚举变量) - 整数 → 枚举:强制类型转换
TAnimalKind(整数) - 转换整数到枚举前,务必校验数值范围:合法区间
0 ~ Ord(High(枚举类型))
type
TAnimalKind = (akDuck, akCat, akDog);
var
Kind: TAnimalKind;
Num: Integer;
begin
Kind := akCat;
Num := Ord(Kind); // akCat 序号为1,Num=1
Num := 2;
// 先校验数值合法再转换
if (Num >= 0) and (Num <= Ord(High(TAnimalKind))) then
Kind := TAnimalKind(Num);
end;Code language: JavaScript (javascript)
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;
type
TAnimalKind = (akDuck, akCat, akDog);
var
Kind: TAnimalKind;
Num: Integer;
begin
Kind := akCat;
Num := Ord(Kind); // akCat index is 1,Num=1
Num := 2;
if (Num >= 0) and (Num <= Ord(High(TAnimalKind))) then
Kind := TAnimalKind(Num);
WriteLn(Num);//2
end.Code language: PHP (php)

Previous: 多值条件判断(case 语句)
Next: 枚举数组和集合