我正在尝试将一个集合存储在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;
答案 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
...