我正在查看.NET 4.5.1 ArrayList
类的the implementation,我注意到它在内部存储了一个版本号,用于跟踪对列表所做的更改。某些观察者类(如ArrayList
的枚举器)使用此版本号来检查列表是否在该只读操作期间被修改。
该版本号是int
,只是一个计数器:每个可变操作都会增加版本号。因此,我们能够在ArrayList
上执行有限数量的可变操作,直到版本号溢出。
默认情况下,整数溢出不会在C#中抛出异常,因此ArrayList
的版本号可能会发生溢出,而不会立即抛出异常。我的问题是:是否保证ArrayList
的版本号不会溢出,或者如果它确实溢出,基于版本号的检查过程不会失败?
我想到的是一个应用程序对大量元素进行操作会导致ArrayList
s版本号溢出导致ArrayList
版本错误。
答案 0 :(得分:4)
不,它不能保证。但你不应该担心这一点。你很可能不会遭受这种行为。
然而,你可以想象一下情况,例如你得到一个枚举器,使用GetEnumerator
方法,开始枚举集合,同时改变它适当的次数使version
计数器溢出并再次返回相同的值。进一步枚举应该会因 Collection changed 消息而失败,但它不会因为version
号与之前完全相同而无法使用。
List<T>
。
答案 1 :(得分:2)
当它溢出时(例如,如果你每天以每秒68次操作,一年一次),它将变为-2,147,483,648。对它的唯一检查是与上一个已知版本相等,而不是“大于/小于”(afaik),所以你不会得到任何错误。
因此,您只担心它会溢出,并且在检查之间再次成为相同的数字。虽然可能,但这是极不可能的:
稍后编辑:我想这里最重要的一点是,你不应该真的能够做到这一点。如果您同时(同步或并行)枚举添加和删除,则使用错误的方法:使用BlockingCollection
,事件,反应类型编程之类的东西,或者只需将ArrayList
锁定为多个线程访问。因此,这是一个很好的理论问题,你永远不必担心它。
†如果您每秒添加6000万个项目,并且需要花费10分钟来枚举整个arraylist中的单个项目,从而发现版本更改,您还需要担心其他事项。 / p> 确切地说,
‡ 1 in 4,294,967,296