如何在TStringList对象中存储一个集合?

时间:2010-02-03 10:34:03

标签: delphi

我正在尝试将一个集合存储在TStringList的对象属性(并读取它)中(我也将使用它来存储与该集合相关联的文本),但是我得到了一个无效的类型转换。

在StringList对象中存储集合的最佳方法是什么?此外,在销毁StringList时是否需要释放此对象?

以下是一些示例代码:

type
 TDummy = (dOne, dTwo, dThree);
 TDummySet = set of TDummy;


var
  DummySet: TDummySet;
  SL: TStringList;
begin
  SL := TStringList.Create;
  Try
    DummySet := [dOne, dThree];
    SL.AddObject('some string', TObject(DummySet)); // Doesn't work. Invalid typecast
  Finally
    SL.Free;
  End;
end;

5 个答案:

答案 0 :(得分:5)

首先阅读其他答案 - 可能你会找到一个不太讨厌的解决方案。

但是FTR:你可以写

SL.AddObject('some string', TObject(Byte(DummySet)));

DummySet := TDummySet(Byte(SL.Objects[0]));

如果你真的想要。

注意:如果向TDummySet类型添加足够的元素,则必须更改关键字Byte。例如,如果您再添加六个元素(因此总共有九个元素),则需要转换为Word

答案 1 :(得分:4)

我无法在这种情况下添加非对象。

您可以做的是创建一个将TDummySet作为Field的对象。 像

这样的东西
TExemple = class
 DummySet = TDummySet;
end;

或者你可以使用不同的方法:

声明:

  TDummy = (dOne, dTwo, dThree);
  TDummySet = set of TDummy;
  PDummySet = ^TDummySet;

使用方法:

var
  DummySet: PDummySet;
 begin
  New(DummySet);
  DummySet^ := [dOne, dThree];

答案 2 :(得分:2)

您不应该通过TStringList.Objects存储集合,因为对象使用(TObject)是32位值类型,并且集合最多可以表示256位,具体取决于集合的大小。这可能是编译器甚至不允许进行转换的原因。

序列化集合的更好方法是使用RTTI。我不确定VCL在哪里公开其内置集序列化机制,但JCL有一个 JclRTTI 单元,其中 JclSetToStr JclStrToSet 函数。< / p>

var 
  fs: TFontStyles;
begin 
  JclStrToSet(TypeInfo(TFontStyles), fs, 'fsBold, fsItalic'); // from string
  Showessage(JclSetToStr(TypeInfo(TFontStyles), fs));         // to string  
end;

答案 3 :(得分:0)

我认为不应该使用字符串列表。为什么不是一个TDummySet数组?不,没有必要释放它,因为集合不是一个对象。

var
  Test: Array of TDummySet;

SetLength(Test, 2);
Test[0] := [dOne, dThree];
Test[1] := [dTwo];

完成后:

SetLength(Test, 0);

答案 4 :(得分:0)

你不能从你的set to TObject进行类型转换,因为你的变量不是指针。

您必须在TStringList中存储指向变量的指针。在这种情况下,您还必须手动分配和解除分配。

尝试这样的事情:

type
  TEnum = (one, two, three);
  TSet = set of TEnum;
  PSet = ^TSet;
var s: TStringList;
    p: PSet;
begin
  s := TStringList.Create;
  p := AllocMem(SizeOf(TSet));
  p^ := [two, three];
  S.AddObject('a', TObject(p));

  // bla bla bla

  // Here you read the set in the string list
  if (two in PSet(S.Objects[0])^)) then begin
    // your checks here
  end

  ...