【问题标题】:LIST<> AddRange throwing ArgumentExceptionLIST<> AddRange 抛出 ArgumentException
【发布时间】: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&lt;T&gt; 不是线程安全的时,这是 List&lt;T&gt; 无法处理的事情之一。
  • 我没有写代码,我只是在调试问题。维护人员在翻找时会发现很多奇怪的东西:)
  • 调用 FindObjects(someOtherParam) 会发生什么?我认为提供了预期的列表?
  • 正确。我自己无法重现此问题,但有人提供了此问题发生的堆栈跟踪,所以我知道它至少发生过一次。

标签: c# exception list


【解决方案1】:

您是否尝试从多个线程更新同一个列表?这可能会导致问题...List&lt;T&gt; 对多个作者来说是不安全的。

【讨论】:

  • FindObjects() 方法本身实例化一个新的 List 对象,填充它并返回它。它们都是单线程的,所以我认为多个线程不可能在 List 上工作。
  • @Tim:那我不明白为什么会这样。看看你是否能想出一个简短但完整的程序来演示这个问题。如果我们可以重现它,我们应该能够修复它。
  • 这或多或少是我希望听到的。我无法重现这个问题,在我看来它不应该发生。我只是想确保我没有遗漏什么,然后直接拒绝它作为一个问题。
  • 你遇到的问题是它肯定已经发生了,正如你所说的,你有一个堆栈跟踪来证明它。我认为最有可能是并发问题 - 例如,您确定它不是由 UI 按钮启动的后台任务,并且用户快速连续单击了两次?
【解决方案2】:

老实说,我不确定,但为什么不直接删除 List 初始化时的大小声明呢?

List`<MyType>` list = new List`<MyType>`

【讨论】:

  • 因为初始化被立即丢弃。它甚至不需要以这种方式初始化。
猜你喜欢
  • 1970-01-01
  • 2012-08-10
  • 2018-11-11
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 2021-12-01
  • 1970-01-01
  • 2010-10-17
相关资源
最近更新 更多