是否保证ArrayList的版本号不会溢出

本文关键字:溢出 版本号 ArrayList 是否 | 更新日期: 2023-09-27 18:00:19

我正在研究.NET 4.5.1 ArrayList类的实现,我注意到它在内部存储了一个版本号,以跟踪对列表所做的更改。一些观察者类(如ArrayList的枚举器)使用此版本号来检查在该只读操作期间是否修改了列表。

这个版本号是一个int,只是一个计数器:每个可变操作都会增加版本号。因此,我们能够在ArrayList上执行有限数量的可变操作,直到版本号溢出为止。

在C#中,整数溢出默认不会引发异常,因此ArrayList的版本号可能会发生溢出,而不会立即引发异常。我的问题是:是否保证ArrayList的版本号不会溢出,或者如果溢出,基于版本号的检查过程不会失败

我想到的是一个应用程序对大型元素集执行操作,这些操作会溢出ArrayList的版本号,从而导致ArrayList版本控制错误。

是否保证ArrayList的版本号不会溢出

不,不能保证。但你不应该担心。你真的不可能因为这种行为而痛苦。

然而,您可以想象这样的情况,例如,当您获得一个枚举器时,使用GetEnumerator方法,开始枚举集合,同时更改适当的次数以使version计数器溢出并再次返回到相同的值。如果Collection changed消息,则进一步的枚举应该会失败,但不会,因为version编号与以前完全相同。

顺便说一句,同样的事情也适用于例如List<T>

当它溢出时(例如,如果在一年中每天操作>68次),它将变为-2147483648。对它的唯一检查是与上一个已知版本是否相等,而不是"大于/小于"(afaik),这样你就不会出现任何错误。

因此,你只担心它会溢出,并在两次检查之间再次变成相同的数字。虽然可能,但极不可能:

  1. 每秒添加6000万次,仍然需要>10分钟才能达到相同的数字,然后您需要在那之前进行检查,才能"看不到"最后43亿次版本更改。你不太可能看到这种情况发生
  2. 您还需要在数字递归的同时进行检查,这也是极不可能的
  3. 如果你真的看到了,那就买一张彩票,这一定是你的幸运周

稍后编辑:不过,我想这里最重要的一点是,你不应该真的能够做到这一点。如果您在同时(同步或并行)添加和删除时枚举,则使用了错误的方法:使用BlockingCollection、事件、反应型编程之类的方法,或者仅锁定ArrayList进行多线程访问。因此,这是一个很好的理论问题,你永远不应该担心它

如果你每秒添加6000万个项目,并花10分钟在整个数组列表中枚举一个项目,从而发现版本更改,那么你还有其他事情要担心。

4294967296中的1,精确地说是