2015-04-28 72 views
2

我有以下代码操作与记录在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); 

我刚刚添加的逻辑表达式

回答

1

编译器知道如何将一条记录分配给另一条记录,所以您不需要为此做任何特殊的事情。另一方面,如果你想比较记录,你必须手动实现。

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

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

这是不必要的复杂。直接调用'Default'即可。你的通用方法很麻烦。我怀疑你相信'Default'是一个通用函数。事实并非如此。 –

+0

@DavidHeffernan:我只是想''Default()'不能用于泛型之外,而不是泛型。就像你说的那样,它并没有被Embarcadero记录下来,每一篇我可以发现提到'Default()'的博客文章总是与泛型相关,从不独立。我从来没有使用过它。 –

+0

它是那些内部函数之一,有点像新的'GetTypeKind',它传递了一个类型引用。这可以是泛型类型或方法内的通用参数,也可以是具体类型。如果他们记录它真的会很好。这是一个血腥的有用功能。 –

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

0

您可以使用Record*()功能,可在我们的开源SynCommons.pas unit

你就可以这样写:

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)); 
... 

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

所以这个功能从Delphi 6到XE8以及FreePascal都有效。

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