我们可以将字符串和一些关联的对象添加到TStringList:
list: TStringList; obj: MyObject; obj := MyObject.Create(); list.AddObject("real object",obj);
另外,简单地将字符串与指针连接起来非常方便,即整数值,如下所示:
list.AddObject("just an index",Pointer(7));
如果我以后访问此列表中的对象,如何知道它是MyObject还是仅仅是指针?我想要这样的东西:
for i := 0 to list.Count-1 do if list.Objects[i] is MyObject then begin // ... // Do something with list.Objects[i] // ... end;
但是如果list.Objects [i]只是一个指针,这显然会导致访问冲突.
提前致谢!
解决方法
如果要将整数和对象安全地存储到一个字符串列表中,请定义一个变量容器类来保存整数或对象.
下面是这样一个粗略概述的类,包括一个测试项目.
unit VariantContainer; interface uses Variants,SysUtils; Type TVariantContainer = class private FVariant : Variant; public constructor Create(aValue: Integer); overload; constructor Create(aValue: TObject); overload; function IsInteger: Boolean; function IsObject: Boolean; function AsObject: TObject; function AsInteger: Integer; end; implementation function TVariantContainer.AsInteger: Integer; begin if not IsInteger then raise Exception.Create('Variant is not Integer'); Result := FVariant; end; function TVariantContainer.AsObject: TObject; begin if not IsObject then raise Exception.Create('Variant is not TObject'); Result := TVarData(FVariant).VPointer; end; function TVariantContainer.IsInteger: Boolean; begin Result := VarIsType( FVariant,varInteger); end; function TVariantContainer.IsObject: Boolean; begin Result := VarIsType(FVariant,varByRef); end; constructor TVariantContainer.Create(aValue: Integer); begin Inherited Create; FVariant := aValue; end; constructor TVariantContainer.Create(aValue: TObject); begin Inherited Create; TVarData(FVariant).VType:= VarByRef; TVarData(FVariant).VPointer:= aValue; end; end.
program ProjectTestVariantContainer; {$APPTYPE CONSOLE} uses Variants,SysUtils,Classes,VariantContainer; Type TMyObj = class s:String; end; var sList: TStringList; o: TMyObj; i: Integer; begin o := TMyObj.Create; o.s := 'Hello'; sList := TStringList.Create; sList.OwnsObjects := True; // List owns container objects sList.AddObject('AnInteger',TVariantContainer.Create(3)); sList.AddObject('AnObject',TVariantContainer.Create(o)); for i := 0 to sList.Count-1 do begin if Assigned(sList.Objects[i]) then begin if TVariantContainer(sList.Objects[i]).IsInteger then WriteLn( TVariantContainer(sList.Objects[i]).AsInteger) else if TVariantContainer(sList.Objects[i]).IsObject then WriteLn( TMyObj(TVariantContainer(sList.Objects[i]).AsObject).s); end; end; ReadLn; o.Free; sList.Free; end.