【发布时间】:2010-04-07 14:28:46
【问题描述】:
我有一个特殊的方法偶尔会因 ArgumentException 而崩溃:
Destination array was not long enough. Check destIndex and length, and the array's lower bounds.:
at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
at System.Collections.Generic.List`1.CopyTo(T[] array, Int32 arrayIndex)
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
导致此崩溃的代码如下所示:
List<MyType> objects = new List<MyType>(100);
objects = FindObjects(someParam);
objects.AddRange(FindObjects(someOtherParam);
根据 MSDN,List.AddRange() 应该根据需要自动调整大小:
如果新的 Count(当前的 Count 加上集合的大小)会大于 Capacity,则通过自动重新分配内部数组来增加 List)>) 的容量以容纳新元素,并且在添加新元素之前将现有元素复制到新数组中。
有人能想到在什么情况下 AddRange 会抛出这种类型的异常吗?
编辑:
回答有关 FindObjects() 方法的问题。它基本上看起来像这样:
List<MyObject> retObjs = new List<MyObject>();
foreach(MyObject obj in objectList)
{
if(someCondition)
retObj.Add(obj);
}
【问题讨论】:
-
FindObjects返回什么?还有,为什么要初始化objects,然后在下一行立即重新分配? -
当你添加一个项目时,它会检查大小是否足够大,如果不够,它会调整它使用的内部数组的大小。然而,当使用多个线程时,可能会检查,得到一个错误并调整数组的大小,下一个线程读取有足够的空间并且不调整大小,然后它们同时到达实际的
this._items[this._size++] = item;代码......导致后一个线程爆炸。当 Jon 在下面的答案中说List<T>不是线程安全的时,这是List<T>无法处理的事情之一。 -
我没有写代码,我只是在调试问题。维护人员在翻找时会发现很多奇怪的东西:)
-
调用 FindObjects(someOtherParam) 会发生什么?我认为提供了预期的列表?
-
正确。我自己无法重现此问题,但有人提供了此问题发生的堆栈跟踪,所以我知道它至少发生过一次。