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