2015-04-28 111 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