在Delphi中记录操作

时间:2015-04-28 14:12:12

标签: delphi

我有以下代码

type
  TEnumTest = (
   Hello1 = 0,
   Hello2 = 1,
   Hello3 = 2,
   Hello4 = 3,
   Hello5 = 4
);

type
   TRecordTest1 = record
       testa : Integer;
       testb : AnsiString;
       testc : Boolean;
       testd : LongWord;
end;

type
   TRecordTest2 = record
       testa : Integer;
       testb : AnsiString;
       testc : Boolean;
       testd : TEnumTest;
end;

type
   TRecordTest3 = record
       testa : Integer;
       testb : AnsiString;
       testc : Boolean;
       testd : TEnumTest;
end;

type
   TRecordTest4 = record
       testa : Integer;
       testb : AnsiString;
       testc : Boolean;
       testd : TEnumTest;
end;

type 
    TtestRecord = record
      test1 : TRecordTest1;
      test2 : TRecordTest2;
      test3 : TRecordTest3;
      test4 : TRecordTest4;
end; 

有没有办法使用反射或其他机制,所以我可以做以下操作:

var
  a : TtestRecord;
  b : TtestRecord;
if a = b then
begin
  ..............
  ..............
end;
clearAllValues(a);

我刚刚添加了逻辑表达式

3 个答案:

答案 0 :(得分:3)

比较两个记录是否相等

您当然可以使用RTTI来执行记录比较。但是,我想我会通过使用带有比较运算符的扩展记录来做到这一点。例如:

type
  TMyRecord = record
    i: Integer;
    s: string;
    class operator Equal(const lhs, rhs: TMyRecord): Boolean;
    class operator NotEqual(const lhs, rhs: TMyRecord): Boolean;
  end;

class operator TMyRecord.Equal(const lhs, rhs: TMyRecord): Boolean;
begin
  Result := (lhs.i = rhs.i) and (lhs.s = rhs.s);
end;

class operator TMyRecord.NotEqual(const lhs, rhs: TMyRecord): Boolean;
begin
  Result := not (lhs = rhs);
end;

清除记录

您可以使用内部函数Default来默认初始化任何类型。我包含了一个文档链接,但遗憾的是,这个功能没有记录。

您可以像这样编写代码:

var
  a: TTestRecord;
...
a := Default(TTestRecord); // a is replaced with default initialized value

未记录的Default函数将类型标识符作为其参数,并返回该类型的默认初始化实例。因此,数字类型初始化为零,字符串为'',指向nil等等。

答案 1 :(得分:1)

编译器知道如何将一条记录分配给另一条记录,因此您无需为此做任何特殊操作。另一方面,如果要比较记录,则必须手动实现。

为了以一般方式清除记录,可以使用Extended RTTI在Delphi 2010+中完成。但这将是很多手动编码。编译器已经知道如何初始化记录,特别是当它包含任何编译器管理的类型(如字符串)时。让编译器为您使用该反射,例如:

var
  a : TtestRecord;
  b : TtestRecord;
begin
  a := b;
  a := Default(TtestRecord);
end;

答案 2 :(得分:0)

您可以使用我们的开源SynCommons.pas unit中提供的Record*()函数。

你可以写:

var
  a : TtestRecord;
  b : TtestRecord;
...
  if RecordEquals(a,b,TypeInfo(TtestRecord)) then 
    writeln('a=b');
  RecordClear(a,TypeInfo(TtestRecord));
...

您有许多其他功能,例如快速二进制或JSON序列化。

var tmp: RawByteString;
    json: RawUTF8;
...
  tmp := RecordSave(a,TypeInfo(TtestRecord));
...
  RecordLoad(b,pointer(tmp),TypeInfo(TtestRecord));
...
  json := RecordSaveJSON(a,TypeInfo(TtestRecord));
  RecordLoadJSON(b,pointer(json),TypeInfo(TtestRecord));
...

自Delphi 2010以来,JSON序列化将使用高级RTTI。在Delphi 2010之前,您只需使用一些文本注册类型。

所以这个功能从Delphi 6到XE8,以及FreePascal。

作为参考,请查看the corresponding documentation of our framework