Avoid Collection已被修改错误
本文关键字:修改 错误 Collection Avoid | 更新日期: 2023-09-27 17:58:46
问题:
我有以下代码:
foreach(var ItemA in GenericListInstanceB)
{
ItemA.MethodThatCouldRemoveAnyItemInGenericListInstanceB();
}
很明显我犯了一个错误。
我想做的是将GenericListInstanceB
更改为我创建的类,以跟踪它应该删除的项。然后,当循环结束时,它会将它们全部删除。与添加项目相同。
这很好,我可以创建一个类,它有一个内部列表,以及一个要添加和删除的项目列表。然后是另一个名为AddRemovePendingItems
的方法,它实际上"更新"了列表(相应地删除和添加项目)。棘手的部分是让该方法自动调用。
想法:也许看看什么时候调用GetEnumerator
?也许用IDisposable
做点聪明的事?
问题:我如何知道for循环何时退出,并且我们已经完成了对我的集合类的迭代,以便我可以调用我的AddRemovePendingItems
方法?,尤其是如果循环中断早的话?
注意我想避免任何不必要的复制,因为我想消除/尽量减少垃圾收集,这样我就不能只迭代一个副本/制作一个新副本或类似的东西。
您提到了IDisposable
,它提供了一种实现此功能的方法:
public class GenericList<T> : IList<T>
{
private class CleanupEnumerator<T> : IEnumerator<T>
{
private readonly GenericList<T> source;
public CleanupEnumerator<T>(GenericList<T> source)
{
this.source = source;
}
public void Dispose()
{
source.RemovePendingDeletes();
}
/* Other IEnumerator methods here */
}
public IEnumerator<T> GetEnumerator()
{
return new CleanupEnumerator(this);
}
/* Other IList methods here */
}
这将保证在任何时候使用foreach
枚举集合时,都会在释放枚举器时调用RemovePendingDeletes()
函数。但是,请注意,如果您直接调用GetEnumerator()
并忘记处理枚举器,这可能会变得很糟糕。
这个怎么样。我假设MethodThatCouldRemoveAnyItemInGenericListInstanceB
函数从列表中的任何位置删除一个项目或不删除任何项目,则不会添加任何项目。
bool finished = false;
int i = 0;
while (!finished)
{
var itemA = genericListInstanceB[i];
itemA.MethodThatCouldRemoveAnyItemInGenericListInstanceB();
if (genericListInstanceB[i] == itemA)
i++;
// All other outcomes result in us leaving i alone
finished = (i > (genericListInstanceB.Count - 1));
}
危险、过时、"有臭味",但它可以随心所欲,而不必有一个专门的清单或一些魔法来诱捕清单的处理。