数组
可以使用用户定义的枚举类型进行索引。例如:
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 的泛型,但我非常有兴趣了解有更简单的方法来实现这一点。
最佳答案
我认为泛型将是迄今为止最优雅的解决方案。使用它们就像重写上面的类一样简单:
TEIStringList<T> = class(TStringList)
然后将所有 TIndexValue 引用替换为 T。然后您就可以像任何其他泛型一样创建它:
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 循环中使用。不过,这可能最终会达不到目的。我仍然不确定目的是什么,或者为什么这会有用,但无论如何,这里有一些关于如何做到这一点的想法。
关于Delphi:用于索引 TStringList 项的 Integer 以外的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9365290/