如何在Delphi中将常量字符串分组在一起

如何在Delphi中将常量字符串分组在一起,delphi,Delphi,I使用字符串表示项目在其生命周期内可能处于的不同状态的应用程序 即 开放, 活跃的, 关闭 删除 等等,目前它们都是硬编码成这样的代码 MyVar := 'OPEN'; 我正在努力改变这一点,因为这可能是一个维护问题,所以我想把它们都改成常数,我打算这样做 MyVar := STATUS_OPEN; 但是我想把它们组合成一个数据结构,就像这样 MyVar := TStatus.Open; 在delphi 2007中,最好的方法是什么 我知道我可以为此创建一个记录,但是如何用值填充它,以便系

I使用字符串表示项目在其生命周期内可能处于的不同状态的应用程序

开放, 活跃的, 关闭 删除

等等,目前它们都是硬编码成这样的代码

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中失败要好得多

如果您非常关心第一个问题,您可以在查找数组中使用一条记录,并在每条记录中包含枚举值,并验证单元初始化的顺序。这在频繁维护的任务关键型系统中多次节省了我的时间。此方法还可用于向each值(一个非常方便的特性)

祝你好运

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

同意。为了完整起见,类const方法中既没有代码也没有运行时实例化。我同意您的解决方案是一个很好的解决方案,它还允许“MyVar:=TStatus.Open;”赋值。我回答的这一部分是对这个问题的回答,谈到“必须将其分配给变量或创建对象”。从来没有必要这样做。我非常同意你写的所有内容,但是我真的不明白这与这个问题有什么关系?你提出了一个很好的解决方案,这个问题
Sample usage:

    ShowMessage(ItemStatusConst.ACTIVE);
    ShowMessage(ItemStatusConst.CLOSED);
type
  TRecordName = record
    Field1: Integer;
    Field2: String
  end;

const
  itemstatus : TRecordName = (
    Field1: 0;
    Field2: 'valueoffield2'
  );