如何保存/加载类型集?

XBa*_*000 17 delphi types typecast-operator

我有这个代码

type
  TXSample = (xsType1, xsType2, xsType3, xsType4, xsType5, xsType6, xsType6, xsTyp7, xsType8); // up to FXSample30;  
..

private
  FXSample = Set of TXSample;  
..

published
  property Sample: TXSample read FXSample  write FXSample; 
..

  //if Sample has a value of
  Sample := [xsType2, xsType4, xsType5, xsType6, xsTyp7];
Run Code Online (Sandbox Code Playgroud)

如何保存/加载Sample的属性?
我想将它保存在数据库中.
可能吗?

NGL*_*GLN 25

如果你的集合永远不会超过32种可能性(Ord(High(TXSample)) <= 31),那么将集合强制转换为一个Integer和后面是完全没问题的:

type
  TXSamples = set of TXSample;
var 
  XSamples: TXSamples;
begin
  ValueToStoreInDB := Integer(XSamples);
  Integer(XSamples) := ValueReadFromDB;
end;
Run Code Online (Sandbox Code Playgroud)

更具体一点:SizeOf(TXSamples)必须精确地等于SizeOf(StorageTypeForDB).因此,以下范围适用于Ord(High(TXSample))类型转换TXSamples为:

  • Byte: Ord(High(TXSample)) < 8
  • Word: 8 <= Ord(High(TXSample)) < 16
  • Longword: 16 <= Ord(High(TXSample)) < 32
  • UInt64: 32 <= Ord(High(TXSample)) < 64


小智 6

在Delphi中无法直接对类变量进行类型转换,但内部Delphi将该集存储为字节值.通过使用无类型移动,可以很容易地将其复制到整数中.请注意,这些函数最多只能达到32(整数的边界).要增加边界,请改用Int64.

function SetToInt(const aSet;const Size:integer):integer;
begin
  Result := 0;
  Move(aSet, Result, Size);
end;

procedure IntToSet(const Value:integer;var aSet;const Size:integer);
begin
  Move(Value, aSet, Size);
end;
Run Code Online (Sandbox Code Playgroud)

演示

type
  TMySet = set of (mssOne, mssTwo, mssThree, mssTwelve=12);
var
  mSet: TMySet;
  aValue:integer;
begin
  IntToSet(7,mSet,SizeOf(mSet));
  Include(mSet,mssTwelve);
  aValue := SetToInt(mSet, SizeOf(mSet));
end;
Run Code Online (Sandbox Code Playgroud)