delphi – 为什么Generics.Collections.TObjectList.List不安全?

delphi – 为什么Generics.Collections.TObjectList.List不安全?,第1张

概述Generics.Collections中的TList和TOjectList具有.List属性,它是一个枚举器. 例如: oList := TObjectList<TItem>.Create;// Add items to oListfor Item in oList.List do begin // Do something with Itemend; 这很整洁,但结果却很严重. .L Generics.Collections中的TList和TOjectList具有.List属性,它是一个枚举器.

例如:

oList := TObjectList<TItem>.Create;// Add items to oListfor Item in oList.List do begin  // Do something with Itemend;

这很整洁,但结果却很严重. .List只读取FList(TList和TObjectList上的私有声明),它只是一个arrayofT.

由于动态数组在添加超出其大小的项目时大小加倍,这意味着它具有未使用项目的空间.

如果您添加了3个TItems,则实际FList长度为4个项目,第四个(和最后一个)项目为nil.

因此,使用TObjectList的.List是不安全的,因为如果你的TObjectList没有功率为2的.Count值(例如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是否为零.)

我的问题是这样的:

>为什么.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: 4Found: "line"Found: "line"Found: "line"Found: ""
解决方法

TList<T> and TOjectList<T> in Generics.Collections have a List property,which is an enumerator.

不,不是这样. List属性是动态数组.动态数组内置了对枚举的支持.

Since a dynamic array is doubled in size whenever an item is added beyond its size,it means it has space for non-used items.

那也不是真的.动态数组不会自动调整大小.必须通过调用SetLength显式调整它们的大小. TList< T> class使用对SetLength的调用来管理存储列表内容的基础动态数组的容量.

Why is List not an actual enumerator?

如果我记得的话,最近在XE3中添加了List属性.其目的是允许直接访问基础列表,这是其他方式无法实现的.

有时为了提高效率,如果要修改列表内容,可能更愿意避免复制.例如,假设您的列表包含大小为1KB的记录.如果要在不使用List属性的情况下修改每个记录中的单个布尔值,最终会将整个1KB记录复制两次.只是修改一个布尔值.

当然,获得对底层存储的访问的成本是您接触到内部实现细节. Embarcadero可以实现以更安全的方式为您提供访问权限的功能,但无论出于何种原因,他们都选择了这条路线.我想我可能已经创建了一个索引属性,它返回一个指向项目的指针.

所以,这实际上是List属性的唯一用例.除非您确实需要直接访问底层存储,否则请勿使用List.当然,如果文档不愿解释任何这一点,那就太好了,但事实就是如此.

Does TList<T> have an actual enumerator?

是的,它确实.

var  Item: SomeType;  MyList: TList<SomeType>;....for Item in MyList do  Item.Foo();
总结

以上是内存溢出为你收集整理的delphi – 为什么Generics.Collections.TObjectList.List不安全?全部内容,希望文章能够帮你解决delphi – 为什么Generics.Collections.TObjectList.List不安全?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1272965.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存