如果原始集合修改了.NET,枚举数将发生什么

|| 我有一个通用的Tree类,它将实现ICollection (并因此实现IEnumerable 和IEnumerable)。 为此,我必须实现一个TreeEnumerator类。 每次对Tree.GetEnumerator()的调用都将返回TreeEnumerator的新实例。 我有两个问题: 如果周围有很多TreeEnumerator对象并且基础Tree发生了变化,那么会发生什么?如何处理? 创建TreeEnumerator时是否最好对所有树元素(在TreeEnumerator内部进行CopyToArray操作)以方便进行数组遍历,还是对每个MoveNext一次一次遍历? 我知道CopyToArray很容易进行一次遍历,但是会占用空间。 编辑: 了解版本机制后: 您能否指出这种版本控制机制的示例代码?必须有标准的命名方式和访问方式,因为foreach循环在每次MoveNext时都需要进行此检查     
已邀请:
        通常,对基础集合的结构更改会使所有现有的迭代器无效。可以使用集合中的“版本号”来实现,可以在每个迭代步骤中进行检查。 例如,从文档中获取“ 0”:   只要集合保持不变,枚举数将保持有效。如果对集合进行了更改(例如添加,修改或删除元素),则枚举数将无法恢复,并且其行为是不确定的。 (实际上,它会抛出
InvalidOperationException
。) 请注意,.NET 4中的并发集合显式允许在不使迭代器无效的情况下更改集合。通常,迭代器只会看到原始元素,就像调用
GetEnumerator()
时已拍摄快照一样。     
        在框架的集合(例如
List<T>
类)中处理此问题的方式是保留列表状态的版本号。无论何时以任何方式更改列表的内容,都会增加版本号。 枚举器包含版本号的副本,以便在需要访问列表时可以检查列表是否不变。 在创建枚举器时复制项目将避免需要版本计数器,但这也使创建枚举器变得昂贵。对于大多数集合而言,创建枚举数并不昂贵,因此,如果可能,您应尝试遵循这种行为。     
        这确实取决于实现。如果您在枚举期间更改集合,大多数实现将不会爱您-并会故意抛出异常。但是,有可能(主要是仅用于追加的集合,但对所有人都可能)编写一个安全的枚举器(例如,通过枚举创建时已存在的枚举,但是可以进行多种设计)。 就个人而言,我会避免这种情况。最好对其进行设计,以使您可以枚举或变异,但绝不能同时使用。 如果您不能使用支持并发枚举和变异的集合,则可以进行复制,但是再次这样做-不是我的首选。     

要回复问题请先登录注册