我们可以将字符串和一些关联的对象添加到TStringList:
list: TStringList;
obj: MyObject;
obj := MyObject.Create();
list.AddObject("real object", obj);
Run Code Online (Sandbox Code Playgroud)
另外,简单地将字符串与指针连接起来非常方便,即整数值,如下所示:
list.AddObject("just an index", Pointer(7));
Run Code Online (Sandbox Code Playgroud)
如果我以后访问此列表中的对象,如何知道它是MyObject还是仅仅是指针?我想要这样的东西:
for i := 0 to list.Count-1 do
if list.Objects[i] is MyObject then
begin
// ...
// Do something with list.Objects[i]
// ...
end;
Run Code Online (Sandbox Code Playgroud)
但是如果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.
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
完全可以添加一个恰好指向一个对象的整数.同样,很可能有一个指向列表中已经释放了对象的对象的指针.
最重要的是,您可以随心所欲地在内存中查找,没有防弹方法来了解您的stringlist是否包含整数或指针.
因为你不应该混合不同的类型,也没有必要知道.更好的方法是创建两个包含 Stringlist的类,并使外部类类型安全地使用.那么你的问题就成了一个问题.
假设您的Delphi版本不支持泛型的示例
TStringIntegerMap = class
private FStringIntegerList: TStringList;
public
procedure Add(const Key: string; Value: Integer);
... // Add the other required equivalent TStringlist methods
end;
TStringObjectMap = class
private FStringObjectList: TStringList;
public
procedure Add(const Key: string; Value: TObject);
... // Add the other required equivalent TStringlist methods
end;
Run Code Online (Sandbox Code Playgroud)
请注意,这只是为了向您提供有关如何实现此类的要点.