TList
和TOjectList
在Generics.Collections
有一个.List
属性,它是一个枚举.
例如:
oList := TObjectList<TItem>.Create;
// Add items to oList
for Item in oList.List do begin
// Do something with Item
end;
Run Code Online (Sandbox Code Playgroud)
这很整洁,但结果却很严重. .List
只读FList
(在TList
和上的私人声明TObjectList
),这只是一个arrayofT
.
由于动态数组在添加超出其大小的项目时大小加倍,这意味着它具有未使用项目的空间.
如果您添加了3 TItem
秒,则实际FList
为4个项目,第四个(和最后一个)项目为nil
.
因此使用TObjectList
's .List
是不安全的,因为如果你TObjectList
没有.Count
2的幂值(例如1,2,4,8,16等),它可能会引发访问冲突.
以下代码可能会引发访问冲突:
for Item in oList.List do begin
Writeln(Item.ClassName);
end;
Run Code Online (Sandbox Code Playgroud)
当然,安全的解决方案是一个简单的迭代,使用.Count
:
for I := 0 to oList.Count - 1 do begin
Item := oList.Items[I];
Writeln(Item.ClassName);
end;
Run Code Online (Sandbox Code Playgroud)
这不像枚举器那么漂亮.(你也可以检查,如果Item
是nil
的,当然.)
我的问题是这样的:
.List
不是实际的普查员?TList
/ TObjectList
有一个实际的枚举?这是a的一个例子TForm
(其中btn1
只是添加一行而且mmo1
是a 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;
Run Code Online (Sandbox Code Playgroud)
现在,使用string
不会抛出访问冲突.但是,当我点击3次后,我得到以下内容:
Count: 3; Actual length: 4
Found: "Line"
Found: "Line"
Found: "Line"
Found: ""
Run Code Online (Sandbox Code Playgroud)
Dav*_*nan 16
TList<T>
和TOjectList<T>
在Generics.Collections
有一个List
属性,它是一个枚举.
不,不是这样.该List
属性是动态数组.动态数组内置了对枚举的支持.
由于动态数组在添加超出其大小的项目时大小加倍,这意味着它具有未使用项目的空间.
那也不是真的.动态数组不会自动调整大小.必须通过调用显式调整它们的大小SetLength
.本TList<T>
类管理存储使用,以调用列表内容的基本动态数组的能力SetLength
.
为什么
List
不是实际的普查员?
List
如果我记得的话,该物业最近在XE3中被添加.其目的是允许直接访问基础列表,这是其他方式无法实现的.
有时为了提高效率,如果要修改列表内容,可能更愿意避免复制.例如,假设您的列表包含大小为1KB的记录.如果要在不使用List
属性的情况下修改每个记录中的单个布尔值,最终会将整个1KB记录复制两次.只是修改一个布尔值.
当然,获得对底层存储的访问的成本是您接触到内部实现细节.Embarcadero可以实现以更安全的方式为您提供访问权限的功能,但无论出于何种原因,他们都选择了这条路线.我想我可能已经创建了一个索引属性,它返回一个指向项目的指针.
所以,这确实是该List
物业的唯一用例.除非您确实需要直接访问底层存储,否则请勿使用List
.当然,如果文档不愿解释任何这一点,那就太好了,但事实就是如此.
是否
TList<T>
有一个实际的枚举?
是的,它确实.
var
Item: SomeType;
MyList: TList<SomeType>;
....
for Item in MyList do
Item.Foo();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1973 次 |
最近记录: |