回到 .NET Reflector 是免费的时候,我用它来喘口气进入 .NET 框架代码。我注意到 .NET 2.0 中的大多数集合(我相信这也适用于当前版本)使用以下机制来识别循环期间的集合修改:
public class SomeCollection<T>
{
internal int version = 0;
// code skipped for brevity
public void Add(T item)
{
version++;
// add item logic ...
}
public IEnumerator<T> GetEnumerator()
{
return new SomeCollectionEnumerator<T>(this);
}
}
public class SomeCollectionEnumerator<T> : IEnumerator<T>
{
private SomeCollection<T> collection;
private int version;
public SomeCollectionEnumerator(SomeCollection<T> collection)
{
this.version = collection.version;
this.collection = collection;
}
public bool MoveNext()
{
if (this.version != this.collection.version)
{
// collection was modified while iterated over
throw SomeException(...);
}
// iteration logic here...
}
}
现在想象一个长时间运行的应用程序(一个频繁使用的 Web 服务,必须有最少的停机时间并且应该是稳定和可靠的)的假设情况,它将给定的集合实例(.NET 框架中的内置集合类型之一)保存在内存中只要它运行。集合被频繁地修改,以便int.MaxValue
可能发生修改。集合的每个修改方法中的行是否存在引发溢出异常的风险version++
(假设溢出检查未全局禁用)。
我必须承认我对反射代码的细节记忆很差,但我不记得操作unckecked
周围的块的用法version++
。这是否意味着.NET 中的内置集合类型不适合这种长时间运行的应用场景?只是出于好奇,有人遇到过这种情况可能发生的现实场景吗?