【问题标题】:Prevent collection from being modified while enumerating防止在枚举时修改集合
【发布时间】:2014-05-30 09:10:31
【问题描述】:

如何防止 Collection 在枚举期间被修改。

这是类源代码。

 public class cars : IEnumerator,IEnumerable
 {
  private car[] carlist;
  int position = -1;

  public IEnumerator GetEnumerator()
  { return (IEnumerator)this; }

  public bool MoveNext()
  {
     position++;
     return (position < carlist.Length);
  }

  public void Reset()
  {position = 0;}

  //IEnumerable
  public object Current
  { get { return carlist[position];}
  }
 }      

【问题讨论】:

  • @Downvoter:为什么要投反对票?最好告诉 OP 这个问题有什么问题。

标签: c# collections enumeration


【解决方案1】:

首先,你的集合类不应该实现IEnumerator——它应该只实现IEnumerable,并在调用GetEnumerator()时返回另一个实现IEnumerator(可能是carEnumerator)的类的实例。

IEnumerator(在carEnumerator 中实现)扩展了IDisposable,因此,在cars.GetEnumerator() 中,您可以将私有标志(可能是private bool isEnumerating)设置为true。在carEnumerator 中,保留对集合(汽车)的引用,在carEnumerator.Dispose() 中,将isEnumerating 设置回false。

最后,在枚举进行时,在您想要禁用的所有汽车方法中,检查isEnumerating 的状态,如果为真则抛出异常或不执行任何操作。

【讨论】:

  • 注意:IEnumerator 的非通用版本实际上并没有扩展 IDisposable。使用通用接口(IEnumerable、IEnumerator)或标记 carEnumerator 来扩展 IEnumerator 和 IDisposable。在 for-each 语句之后,如果枚举数是一次性的,则将调用 Dispose()。
【解决方案2】:

至少有一些 BCL 集合通过包含版本计数器来做到这一点。对集合的每次修改都会增加计数器。当集合的枚举开始时,版本计数的当前值被保留。每次调用枚举器的 MoveNext 时,都会根据保留的计数器检查底层集合的版本,如果不同则引发异常。

【讨论】:

    猜你喜欢
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 2012-02-18
    相关资源
    最近更新 更多