在我朋友的代码中,他有一个List

 List<int> listOfIds = new List<int>();


然后,我使用AddRange()向其中添加了一个int集合:

   listOfIds.AddRange(this._employeeList
                       .Where(r => r.EmployeeID != null)
                       .Select(r => r.EmployeeID != null ? r.EmployeeID.Value : 0));


但是然后,在日志中,它说:

 System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
   at the method which called the codes above.....


我不太确定为什么会这样。我很确定此错误发生在上面的代码上,但我似乎无法理解为什么会出现IndexOutofRangeException的问题。

您能帮我指出是什么原因造成的吗?

更新:

我错了。我很抱歉。该方法不使用多线程。但是,另一个称为此方法的方法是使用Parallel.Foreach,这意味着多线程。 _employeeList用作AddRange()的源时,另一个线程可能也在修改它。因此,有关addrange()不是线程安全的答案是合理的。十分感谢大家。

最佳答案

很难说出更具体的想法,但这可能行得通。

AddRange不是线程安全的。尝试使用lock primitives添加许多项目。宣布:

private static object mutex = new object();


用法

lock(mutex)
{
    listOfIds.AddRange( /* code goes here */ )
}


反编译后发现AddRange

public void AddRange(IEnumerable<T> collection)
{
  this.InsertRange(this._size, collection);
}


InsertRange的内容,可以在堆栈跟踪中看到:

  ...
  ICollection<T> collection1 = collection as ICollection<T>;
  if (collection1 != null)
  {
     ...
  }
  else
  {
    foreach (T obj in collection)
      this.Insert(index++, obj);
  }


换句话说-迭代序列并尝试使用递增索引逐项添加。这不应该出错,对吗? 845中的List.cs行由dotPeek反编译。因此,我不会相信堆栈跟踪,除非会看到整个堆栈跟踪。

关于c# - LINQ索引超出范围,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14260658/

10-16 08:52