一、列舉型別(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; // 缺少 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; // 完整標註型別限定
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 敘述)