当我清除IndexOutOfRangeException
时,我不知道为什么我有System.Collections.Generic.List<T>
。这有意义吗?
List<MyObject> listOfMyObject = new List<MyObject>();
listOfMyObject.Clear();
答案 0 :(得分:18)
如果多个线程同时访问列表,通常会发生这种情况。如果一个线程删除一个元素而另一个线程调用Clear(),则可能发生此异常。
在这种情况下,“答案”是适当地同步,锁定所有列表访问权限。
编辑:
为了处理这个问题,最简单的方法是将列表封装在自定义类中,并公开所需的方法,但需要锁定。您需要为改变集合的任何内容添加锁定。
这是一个简单的选择:
public class MyClassCollection
{
// Private object for locking
private readonly object syncObject = new object();
private readonly List<MyObject> list = new List<MyObject>();
public this[int index]
{
get { return list[index]; }
set
{
lock(syncObject) {
list[index] = value;
}
}
}
public void Add(MyObject value)
{
lock(syncObject) {
list.Add(value);
}
}
public void Clear()
{
lock(syncObject) {
list.Clear();
}
}
// Do any other methods you need, such as remove, etc.
// Also, you can make this class implement IList<MyObject>
// or IEnumerable<MyObject>, but make sure to lock each
// of the methods appropriately, in particular, any method
// that can change the collection needs locking
}
答案 1 :(得分:7)
您确定该代码会引发异常吗?我有
using System.Collections.Generic;
class MyObject { }
class Program {
static void Main(string[] args) {
List<MyObject> listOfMyObject = new List<MyObject>();
listOfMyObject.Clear();
}
}
我没有例外。
你的现实生活中的例子更复杂吗?也许你有多个线程同时访问列表?我们能看到堆栈跟踪吗?
List<T>.Clear
非常简单。使用Reflector:
public void Clear() {
if (this._size > 0) {
Array.Clear(this._items, 0, this._size);
this._size = 0;
}
this._version++;
}
如果列表已经为空,那就不会抛出异常。但是,如果要修改另一个线程上的列表,Array.Clear
可能会抛出IndexOutOfRangeException
异常。因此,如果另一个线程从列表中删除了一个项目,那么this._size
(要清除的项目数量)将会太大。
答案 2 :(得分:1)
文档没有提到此方法抛出的任何异常,您的问题可能在其他地方
List<T>.Clear