2013-01-10 123 views
2

在我的朋友的代码,他有一个ListLINQ索引越界

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会出现。

你能帮我指出哪些会导致这种情况吗?

UPDATE:

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

+2

这听起来像你从多个线程使用它。 – SLaks

+0

试试此代码:listOfIds.AddRange(this._employeeList 。Where(r => r.EmployeeID!= null) .Select(r => r.EmployeeID!= null?r.EmployeeID.Value:0).ToList ()) –

+0

你的'Where'和'Select'不匹配。你的'EmployeeID'永远不能为空,因为你的'Where'过滤掉了。如果ID为空,你是否真的希望'0'被添加到列表中? –

回答

2

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

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

private static object mutex = new object(); 

使用

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

AddRange编译发现InsertRange

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

内容,您可以在堆栈跟踪看到后:

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

换句话说 - 它遍历序列并尝试使用递增索引逐项添加。这不应该出问题,应该吗? 845List.cs反编译dotPeek。所以我不会相信堆栈跟踪,除非我会看到整个堆栈。

+0

堆栈跟踪中的行'System.Linq.Enumerable.WhereSelectListIterator'2.MoveNext()'提示,错误来自Where子句 – Tilak

+0

我更新了我的答案。任何新想法? –

+0

@Tilak但是堆栈中的顶层方法只是一个普通的'List'上的'MoveNext'调用。 – Rawling