我个人在多个大型关键数据处理平台上广泛使用TOndrej的方法。枚举的好处是它们可以在应用程序内轻松传递,非常紧凑(一种序数类型),在情况语句中完美工作,并且完全类型安全。后一个点对于维护很重要,因为删除或更改枚举值将导致编译错误(我认为这是一件好事)。
使用此方法时要注意以下问题:
- 更改枚举值的声明顺序将破坏枚举到字符串查找数组。
- 如果您在情况语句中使用枚举(一个不错的功能),请确保考虑到新值的添加。我通常在情况下添加一个else,并在未知值上抛出异常。比掉入情况好得多。
- 如果您非常关注第一个问题,可以在查找数组中使用记录,并在每个记录中包含枚举值并从单元初始化验证排序。这在维护频繁的关键系统中多次拯救了我。此方法还可用于向每个值添加其他元数据(一个非常方便的功能)。
祝你好运!
unit Unit1;
interface
type
TItemStatusEnum = (isOpen, isActive, isClosed);
TItemStatusConst = class
class function EnumToString(EnumValue : TItemStatusEnum): string;
property OPEN: string index isOpen read EnumToString;
property CLOSED: string index isClosed read EnumToString;
property ACTIVE: string index isActive read EnumToString;
end;
var
ItemStatusConst : TItemStatusConst;
implementation
uses
SysUtils;
type
TItemStatusRec = record
Enum : TItemStatusEnum;
Value : string;
end;
const
ITEM_STATUS_LOOKUP : array[TItemStatusEnum] of TItemStatusRec =
((Enum: isOpen; Value: 'OPEN'),
(Enum: isActive; Value: 'ACTIVE'),
(Enum: isClosed; Value: 'CLOSED'));
procedure ValidateStatusLookupOrder;
var
Status : TItemStatusEnum;
begin
for Status := low(Status) to high(Status) do
if (ITEM_STATUS_LOOKUP[Status].Enum <> Status) then
raise Exception.Create('ITEM_STATUS_LOOKUP values out of order!');
end;
class function TItemStatusConst.EnumToString(EnumValue: TItemStatusEnum): string;
begin
Result := ITEM_STATUS_LOOKUP[EnumValue].Value;
end;
initialization
ValidateStatusLookupOrder;
end.
更新:
感谢批评 - 你是完全正确的,我解决的是我认为是问题的根本。如果您可以接受这个约束条件,下面是一个简单得多的方法,它只能在Delphi 2007或更高版本中使用(可能在D2006中也可以使用?)。很难摆脱那些令人烦恼的向后兼容性思维;)
type
ItemStatusConst = record
const OPEN = 'OPEN';
const ACTIVE = 'ACTIVE';
const CLOSED = 'CLOSED';
end;
这种方法简单易行,与Java或.Net应用程序的操作感觉相似。使用语义按预期工作,并且可以与代码补全配合使用。其中一个重要优点是常量范围限定在记录级别,因此不会像单位级别类型一样出现与其他定义冲突的风险。
Sample usage:
ShowMessage(ItemStatusConst.ACTIVE);
ShowMessage(ItemStatusConst.CLOSED);
仅出于娱乐目的,我还改进了我早期的方法,直接回答原始问题并获得类似的结果。这次我使用了“模拟类属性”(请参见此处)和属性索引器。这显然比记录方法更复杂,但保留了与枚举值、集合、字符串一起工作的能力,并且还可以扩展以实现其他元数据特性(如果需要)。我相信这适用于Delphi 5及其更高版本。
我曾经成功地使用这种技术创建了一个解析框架,用于处理Delphi中的完整的IBM AFPDS打印数据流语法。这种灵活性就是我喜欢在Delphi中工作的原因——它就像瑞士军刀一样;)