繁体   English   中英

在迭代它时将项添加到List是否安全

[英]Is it safe to add items to the List while iterating through it

我知道不能使用枚举器并同时修改List<T> 添加或删除项目将使枚举器无效( http://msdn.microsoft.com/en-us/library/system.collections.ienumerator(v=vs.110).aspx ),因为内部数组将被重新分配( http://msdn.microsoft.com/en-us/library/3wcytfd1(v=vs.110).aspx )。

  1. 是否总是如此,即使Count小于Capacity ?(据我所知,在这种情况下,数组不会被重新分配,因此枚举器必须有效);
  2. 为什么Current返回它所设置的元素,即使枚举器已经失效?(我的意思是,如果数组被重新分配...);
  3. 重新分配是否保留了项目的原始顺序? 我的意思是如果某个项目的索引为n,在添加和项目后它是否会有相同的索引?(MSDN说Add将一个对象Add到列表的末尾)如果是这样,可以安全地运行常规列表for循环并添加项目,假设循环只迭代每个项目一次,我是否正确?

是否总是如此,即使Count小于Capacity

这可能是也可能不是。 但是,您应该表现得总是如此,因为文档不会对此行为做出任何例外。

List<T> (来自Mono项目)的至少一个实现总是通过在每个更改列表的操作中递增存储在列表内的名为_version的隐藏成员来使所有迭代器无效。 获取迭代器(在.NET中称为Enumerator )时, _version的当前值存储在枚举器对象中。 每次调用MoveNext ,都会将存储的_version与当前的_version进行比较,并在两者不匹配时抛出异常。

为什么Current返回它设置的元素,即使枚举器已经失效?

因为Current的值存储在迭代器中。 虽然有一个很好的理由阻止你在修改集合时进一步迭代,但是可以让你在迭代器有效的位置访问该位置的值。

重新分配是否保留了项目的原始顺序?

是。 这就是为什么即使在列表中添加或删除元素,遍历带有for循环和索引的列表仍然是安全的。

  1. 每次从列表中添加/删除项目时都不会重新分配内部数组,这也不是枚举器失效的原因。 这是一个更好的理由: 收集被修改; 枚举操作可能无法执行 - 为什么?

    简单地说,内部阵列在其容量耗尽时重新分配,并且阵列的大小将加倍。 某些集合还允许您修剪内部数组,例如List<T>.TrimExcess

  2. 为什么不? 该对象仍然存在。

如果您想了解更多信息,请查看源代码 ,特别是在EnsureCapacityList<T>.Enumerator

添加或删除项将使枚举器无效,因为将重新分配内部数组

这部分是正确的。 添加,删除或插入项不会失效枚举因为内部阵列将被重新分配,但是因为List<T>维护version字段内部来跟踪已经发生的变化。 枚举器将使用version字段查找自枚举器创建以来发生的任何新更新。

回答你的问题:

  1. 如果您修改列表而不考虑“Count <Capacity”,则枚举器无效[ 1 ] ,因为它无关紧要。 重要的是版本字段。
  2. 因为枚举器从List中获取当前元素的副本。
  3. 是重新分配保留订单。

1: 并非总是如此 ,实施中存在错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM