2010-04-30 117 views
8

Delphi 2010 如何修改TList <記錄>值?如何修改TList <record>值?

type TTest = record a,b,c:Integer end; 
var List:TList<TTest>; 
    A:TTest; 
    P:Pointer; 
.... 
.... 

List[10] := A; <- OK 
List[10].a:=1; <- Here compiler error : Left side cannot be assined to 
P:[email protected][10]; <- Error: Variable requied 

回答

9
A := List[10]; 
A.a := 1; 
list[10] := A; 

你不必因爲他們是引用類型,(通過編譯器在內部管理,以保持它從你的頭髮,一個指針訪問)使用對象要做到這一點,但記錄值類型,所以它不會那樣工作。

+0

這是一個簡單而強大的方式。但是當記錄的大小非常大時,由於局部變量A,堆棧溢出,並且如果這種情況在循環或循環中起作用,則非常緩慢。 – 2015-07-09 04:18:32

6

您使用記錄時遇到了一些問題。

考慮以下代碼:

function Test: TTest; 
begin 
    ... 
end; 

Test.a := 1; 

實際上是你的代碼看起來像編譯器這樣的:

TTest temp := Test; 
temp.a := 1; 

編譯器告訴你,並顯示錯誤消息,該分配是沒有意義的,因爲它只會給臨時記錄值分配一個新值,這會立即被忘記。

此外,@List[10]是無效的,因爲List[10]再次只返回一個臨時記錄值,因此採取該記錄的地址是沒有意義的。

但是,讀寫整個記錄是可以的。

因此,要總結:

List[10] := A; <- writing a whole record is OK 
List[10].a:=1; <- List[10] returns a temporary record, pointless assignment 
P:[email protected][10]; <- List[10] returns a temporary record, its address is pointless 
+2

但是,屬性項是可讀寫的,我認爲delphi可以理解Items [1] .a:= 123 meens Items [1]:= TType(123,oldval2,oldval3) – Astronavigator 2010-04-30 20:57:26

+0

但它不...重要的部分不是編譯器能夠做什麼,而是它實際做了什麼*。 – 2010-04-30 20:59:20

+1

@Astronavigator:是的,該屬性是R/W,但你不直接訪問該字段。它只是返回一個字段的副本。檢查梅森的答案解決這個問題。 – 2010-04-30 21:19:43

2

如果你想存儲記錄,動態數組更適合處理它們:

type TTest = record a,b,c : Integer end; 
type TTestList = array of TTest; 
var List:TTestList; 
    A:TTest; 
    P:Pointer; 
.... 
.... 

SetLength(List, 20); 
List[10] := A; //<- OK 
List[10].a := 1; //<- Ok 
P := @List[10]; //<- Not advised (the next SetLength(List,xx) will blow the address away), 
       // but technically works 

如果您需要添加的方法來處理這些數據,你可以將此數組存儲爲類的字段,並將您的方法添加到此類中。

1

如果你需要操縱這種形式的對象,最好是使用TObjectList,而不是從TList,並定義結構爲一類,而不是一個紀錄:

type TTest = class a,b,c:Integer end; 
var List:TObjectList<TTest>; 
    A:TTest; // A is an object so there's no need for a pointer 
.... 
.... 
List.Add(TTest.Create); 
List.Last.a := 1; 
A:=List.Last;