【问题标题】:linq index out of boundslinq 索引超出范围
【发布时间】:2013-01-10 14:54:08
【问题描述】:

在我朋友的代码中,他有一个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() 不是线程安全的答案是合理的。非常感谢你们。

【问题讨论】:

  • 听起来你是在多线程中使用它。
  • 试试这个代码:listOfIds.AddRange(this._employeeList .Where(r => r.EmployeeID != null) .Select(r => r.EmployeeID != null ? r.EmployeeID.Value : 0).ToList())
  • 您的 WhereSelect 不匹配。您的 EmployeeID 永远不能为空,因为您的 Where 会将其过滤掉。如果 ID 为 null,您真的希望将 0 添加到您的列表中吗?
  • @Roman,ToList() 有什么帮助?
  • 试试吧。我的猜测是您使用 LINQ 查询而不是收集数据。当您调用 .ToList() 查询时只执行一次,而不是每次都使用 .Next() (AddRange 与 IEnumerable 一起使用)

标签: c# linq list indexoutofboundsexception


【解决方案1】:

很难说出更具体的想法,但这可能会奏效。

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 反编译。所以我不相信堆栈跟踪,除非我会看到整个堆栈跟踪。

【讨论】:

  • 堆栈跟踪中的System.Linq.Enumerable.WhereSelectListIterator'2.MoveNext() 行提示,Where 子句中出现错误
  • @Tilak 但是堆栈中的顶部方法只是对List 的普通MoveNext 调用。
  • @Rawling:注意。我在看可能是错误的方向。我仍然认为问题出在 Linq Query 延迟执行而不是 AddRange 本身(知道不涉及多线程)
  • 我错了。我很抱歉。该方法不使用多线程。但是,另一种调用此方法的方法是使用 Parallel.Foreach。因此,addrange() 不是线程安全的答案是合理的。非常感谢你们。
  • 你永远不能指望代码是单线程的)干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多