3

Arrays可以使用用户定义的枚举类型进行索引。例如:

type
  TIndexValue = (ZERO = 0, ONE, TWO, THREE, FOUR);

var
  MyArray: array[Low(TIndexValue) .. High(TIndexValue)] of String;

然后可以使用TIndexValue值作为索引来引用此数组中的元素:

MyArray[ZERO] := 'abc';

我正在尝试使用TStringList.

一个简单的解决方案是在引用时将每个索引值转换为一个Integer类型:

MyStringList[Integer(ZERO)] := 'abc';

另一个解决方案(隐藏所有转换)是创建一个子类TStringList并将所有转换推迟到该子类的访问继承Strings属性的子例程:

type
  TIndexValue = (ZERO = 0, ONE, TWO, THREE, FOUR);

type
  TEIStringList = class(TStringList)
  private
    function GetString(ItemIndex: TIndexValue): String;
    procedure SetString(ItemIndex: TIndexValue; ItemValue: String);
  public
    property Strings[ItemIndex: TIndexValue]: String 
      read GetString write SetString; default;
  end;

function TEIStringList.GetString(ItemIndex: TIndexValue): String;
begin
  Result := inherited Strings[Integer(ItemIndex)];
end;

procedure TEIStringList.SetString(ItemIndex: TIndexValue; ItemValue: String);
begin
  inherited Strings[Integer(ItemIndex)] := ItemValue;
end;

这适用于使用枚举类型的单个实现TIndexValue

但是,我想TStringList为由不同枚举类型索引的几个不同对象重新使用相同的逻辑或子类,而不必TStringList为每个可能的枚举类型定义子类。

这样的事情可能吗?我怀疑我可能不得不依赖 Delphi 的泛型,但我很想知道有更简单的方法可以实现这一点。

4

2 回答 2

4

我认为泛型将是迄今为止最优雅的解决方案。使用它们就像重写上面的类一样简单:

TEIStringList<T> = class(TStringList) 

然后用 T 替换所有 TIndexValue 引用。然后你可以像任何其他泛型一样创建它:

var
  SL: TEIStringList<TIndexValue>;
begin
  SL:=TEIStringList<TIndexValue>.Create;
  (...)
  ShowMessage(SL[ZERO])
  (...)
end;

如果您坚持避免使用泛型,则可能会使用运算符重载。像下面这样的东西应该可以工作:

type
  TIndexValueHolder = record
    Value : TIndexValue;
    class operator Implicit(A: TMyRecord): integer;
  end;

(...)

class operator TIndexValueHolder.Implicit(A: TMyRecord): integer;
begin
  Result:=Integer(A);
end;

然后使用:

var
  Inx : TIndexValueHolder;

begin
  Inx.Value:=ZERO;
  ShowMessage(SL[Inx]);
end

更新:您可以通过添加 Next、HasNext 等方法来调整 TIndexValueHolder 以在 for 或 while 循环中使用。不过,这可能会以失败告终。我仍然不确定目的是什么,或者为什么这会有用,但无论如何,这里有一些关于如何做到这一点的想法。

于 2012-02-20T19:57:32.283 回答
2

您可能可以使用类助手并将默认属性索引声明为 Variant:

type
  TEnum1 = (Zero = 0, One, Two, Three, Four);
  TEnum2 = (Nul = 0, Een, Twee, Drie, Vier);
  TEnum3 = (Gds = 0, Psajs, Oeroifd, Vsops, Wowid);

  TStringListHelper = class helper for TStringList
  private
    function GetString(Index: Variant): String;
    procedure SetString(Index: Variant; const Value: String);
  public
    property Strings[Index: Variant]: String read GetString write SetString;
      default;
  end;

function TStringListHelper.GetString(Index: Variant): String;
begin
  Result := inherited Strings[Index];
end;

procedure TStringListHelper.SetString(Index: Variant; const Value: String);
begin
  inherited Strings[Index] := Value;
end;

测试代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    Strings.Add('Line 1');
    Strings.Add('Second line');
    Strings[Zero] := 'First line';
    Memo1.Lines.Assign(Strings);
    Caption := Strings[Psajs];
  finally
    Strings.Free;
  end;
end;

有关先前不太成功的尝试,请参阅编辑历史记录。

于 2012-02-20T18:56:59.647 回答