2

在枚举 .NET 集合时,MSDN 指出

只要集合保持不变,枚举数就保持有效。如果对集合进行了更改,例如添加、修改或删除元素,则枚举器将不可恢复地失效,并且其行为未定义。

“不可恢复的无效”究竟是什么意思?

以一棵二叉树为例,它向下引用左右子节点,也向上引用父节点。在这样的树中,对树中单个节点的单个引用就足以在树中导航,因为您可以轻松地从中找到树中的下一个节点。

所以对于那棵树,假设我删除了一些其他节点(大概,我没有删除我当前所在的节点),我还应该使枚举器无效吗?请注意,这里我不是在谈论多线程操作,只是一个运行循环的单个线程,并在循环体内修改集合。

这个“法则”真的就是,一个法则,即使枚举器可以继续,它也不应该?

4

2 回答 2

8

这个“法则”真的就是,一个法则,即使枚举器可以继续,它也不应该?

就个人而言,我认为让你的枚举器抛出,即使它理论上可以继续,也是一种很好的做法。

通常,人们会无意中将更改集合的代码放入 foreach 循环中。如果不这样做,它可能不会在开发人员当前正在测试的特定实例中抛出,但不同的运行时条件很容易让它抛出。

通过总是抛出,你迫使开发人员将你的代码视为框架的集合和枚举,我认为这是一件好事,因为它减少了处理你的库时的意外程度。

于 2010-01-04T18:40:20.777 回答
2

标准集合枚举器的实施使其成为法律。当它们被创建时,它会从集合对象中复制一个私有的“版本”整数。修改集合会增加该版本。迭代器方法比较版本,并在出现不匹配时抛出。没有办法解决这个问题。

但是,有一个集合类允许在枚举集合时修改集合:Microsoft.VisualBasic.Collection。它需要这样做才能与 VB6 Collection 类保持兼容。您可能想看一下它以了解它是如何完成的。IIRC,它在所有迭代器上保留一个 WeakReference,然后在修改集合时更新迭代器。这当然不是万无一失的,删除一个元素并将其重新添加可以枚举同一个对象两次。也不便宜。

于 2010-01-04T18:58:27.713 回答