TList
和TOjectList
在Generics.Collections
有一個.List
屬性,這是一個枚舉。爲什麼Generics.Collections.TObjectList.List不安全?
例如:
oList := TObjectList<TItem>.Create;
// Add items to oList
for Item in oList.List do begin
// Do something with Item
end;
這是整齊的,但有一個激烈的後果。 .List
只讀FList
(TList
和TObjectList
的私人聲明),這僅僅是arrayofT
。
由於動態數組的大小在其大小增加一倍的情況下就會增加一倍,這意味着它爲未使用的項目留有空間。
如果您已添加3 TItem
s,則實際FList
長度爲4個項目,第四個(也是最後一個)項目爲nil
。
因此,使用TObjectList
的.List
是不安全的,因爲它可能會引發訪問衝突,如果您的TObjectList
不具有.Count
值與2(例如,1,2,4,8,16,等等的功率)。
下面的代碼可能會拋出一個訪問衝突:
for Item in oList.List do begin
Writeln(Item.ClassName);
end;
當然,安全的解決方案是使用.Count
一個簡單的迭代:
for I := 0 to oList.Count - 1 do begin
Item := oList.Items[I];
Writeln(Item.ClassName);
end;
這是不漂亮爲統計員。 (你也可以檢查是否Item
是nil
,當然。)
我的問題是這樣的:
- 爲什麼
.List
不是一個實際的枚舉? - 還有
TList
/TObjectList
有一個實際的枚舉?
這裏是從TForm
(其中btn1
簡單地增加一個線和mmo1
是TMemo
)的例子。
procedure TForm2.btn1Click(Sender: TObject);
var
Line: string;
begin
Line := 'Line';
mmo1.Lines.Add(Line);
fList.Add(Line);
mmo1.Lines.Add(Format('Count: %d; Actual length: %d', [fList.Count, Length(fList.List)]));
for Line in fList.List do begin
mmo1.Lines.Add(Format('Found: "%s"', [Line]));
end;
end;
現在,使用string
不會引發訪問衝突。但是,當我點擊了3次,我得到如下:
Count: 3; Actual length: 4
Found: "Line"
Found: "Line"
Found: "Line"
Found: ""
你有沒有意外的一段代碼來證明你的理論?我的意思是,不是那種「可能」的東西,而是真的*失敗。 – JensG
我已經添加了一個例子。 – Svip
我明白了。我只是忽略了'.List'部分,因爲對於我來說這樣使用列表太過分了。但你是對的。 – JensG