如何在Delphi中将常量字符串分组在一起
I使用字符串表示项目在其生命周期内可能处于的不同状态的应用程序 即 开放, 活跃的, 关闭 删除 等等,目前它们都是硬编码成这样的代码如何在Delphi中将常量字符串分组在一起,delphi,Delphi,I使用字符串表示项目在其生命周期内可能处于的不同状态的应用程序 即 开放, 活跃的, 关闭 删除 等等,目前它们都是硬编码成这样的代码 MyVar := 'OPEN'; 我正在努力改变这一点,因为这可能是一个维护问题,所以我想把它们都改成常数,我打算这样做 MyVar := STATUS_OPEN; 但是我想把它们组合成一个数据结构,就像这样 MyVar := TStatus.Open; 在delphi 2007中,最好的方法是什么 我知道我可以为此创建一个记录,但是如何用值填充它,以便系
MyVar := 'OPEN';
我正在努力改变这一点,因为这可能是一个维护问题,所以我想把它们都改成常数,我打算这样做
MyVar := STATUS_OPEN;
但是我想把它们组合成一个数据结构,就像这样
MyVar := TStatus.Open;
在delphi 2007中,最好的方法是什么
我知道我可以为此创建一个记录,但是如何用值填充它,以便系统中的所有对象都可以使用它,而不必每次创建变量并填充值
理想情况下,我希望数据结构和值有一个中心位置,并使它们易于访问(如TStatus.Open),而无需每次使用它时将其分配给变量或创建对象
我相信有一个简单的解决方案,我只是错过了。有什么想法吗?您可以使用记录类型的全局变量。记录类型必须为您的每个状态都有一个字段 您可以在任何单元的Initialize部分中填充记录,调用该单元中声明的过程或函数。您可以有一个单独的单元专门完成这项工作,比如StatusTypes.pas 在接口部分,您可以声明如下内容:
type
TStatus = record
OPEN: string;
end;
var
Status: TStatus;
请参阅(“自Delphi7以来的新Delphi语言功能”
类常量会很好。从上面的链接:
type
TClassWithConstant = class
public
const SomeConst = 'This is a class constant';
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(TClassWithConstant.SomeConst);
end;
正如Jim提到的,您可以使用类常量或枚举类型:
type
TItemStatus = (isOpen, isActive, isClosed);
const
ItemStatusStrings: array[TItemStatus] of string = ('Open', 'Active', 'Closed');
这是您可以在所有版本的Delphi中执行的操作:
type
TStatus = class
class function Active: string;
class function Open: string;
...
end;
class function TStatus.Active: string;
begin
Result := 'ACTIVE';
end;
class function TStatus.Open: string;
begin
Result := 'OPEN';
end;
您可以完全按照自己的意愿使用:
MyVar := TStatus.Open;
只有一个地方可以更改字符串,并且只涉及代码,没有运行时实例化。最近的Delphi版本的新功能并不总是需要这样做…或者您可以将@和@
虽然你可以把它变成一个类或一个记录。虽然如果它是一个类,你可以像@sugged那样添加类函数,而只是从常量数组中获取值。我个人更喜欢将所有字符串都放在常量数组中 在界面中,而不是在实现中的函数主体中插入
class function TGlobalConsts.Active: string;
begin
Result := ItemStatusStrings[itsActive];
end;
class function TGlobalConsts.Open: string;
begin
Result := ItemStatusStrings[itsOpen];
end;
当然,有很多方法可以做到这一点。我个人在几个大型关键任务数据处理平台上广泛使用了TOndrej的方法。枚举的好处是它们可以在应用程序中轻松传递,非常紧凑(有序类型),在case语句中可以完美地工作,并且是完全类型安全的。后一点对于维护非常重要,因为删除或更改枚举值将导致编译错误(一个好主意) 通过这种方法,有些人需要注意:
- 更改枚举值的声明顺序将禁用枚举->字符串查找数组
- 如果您在case语句中使用enum(一个很好的功能),请确保考虑添加的新值。我通常会在case中添加一个else,并对未知值抛出异常。这比在case中失败要好得多
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.
这种方法很简单,与Java或.Net应用程序中的操作有类似的感觉。使用语义与预期一致,并可用于代码完成。一个重要的优点是常量的作用域是记录级别的,因此不会像使用单元作用域类型那样与其他定义发生冲突
Sample usage:
ShowMessage(ItemStatusConst.ACTIVE);
ShowMessage(ItemStatusConst.CLOSED);
只是为了好玩,我还修改了我先前的方法,直接解决了原始问题,得到了类似的结果使用属性索引器。这显然比记录方法更复杂,但保留了使用枚举值、集合、字符串的能力,并且还可以在需要时扩展以实现额外的元数据功能。我相信这适用于Delphi版本,最早可以追溯到Delphi 5 IIRC
我在Delphi中创建了一个解析框架来处理完整的打印数据流语法,这就是我喜欢在Delphi中工作的原因,它就像一把瑞士军刀;)除了TOndrej所说的: 还可以声明记录常量:
type
TRecordName = record
Field1: Integer;
Field2: String
end;
const
itemstatus : TRecordName = (
Field1: 0;
Field2: 'valueoffield2'
);
通过组合上面的const
record语法和TOndrej显示的数组语法,也可以创建记录数组
但是,我通常喜欢的方式需要初始化:
- 通过RTTI使用枚举的名称填充
TStringDynArray
- 如果结果表明名称应该是可配置的,那么持久性(无论如何安排)可以简单地加载/存储dynarray
Sample usage:
ShowMessage(ItemStatusConst.ACTIVE);
ShowMessage(ItemStatusConst.CLOSED);
type
TRecordName = record
Field1: Integer;
Field2: String
end;
const
itemstatus : TRecordName = (
Field1: 0;
Field2: 'valueoffield2'
);