I don't know why I have an IndexOutOfRangeException
when I am clearing a System.Collections.Generic.List<T>
. Does this make sense?
List<MyObject> listOfMyObject = new List<MyObject>();
listOfMyObject.Clear();
I don't know why I have an IndexOutOfRangeException
when I am clearing a System.Collections.Generic.List<T>
. Does this make sense?
List<MyObject> listOfMyObject = new List<MyObject>();
listOfMyObject.Clear();
Are you sure that that code throws an exception? I have
using System.Collections.Generic;
class MyObject { }
class Program {
static void Main(string[] args) {
List<MyObject> listOfMyObject = new List<MyObject>();
listOfMyObject.Clear();
}
}
and I do not get an exception.
Is your real-life example more complex? Perhaps you have multiple threads simultaneously accessing the list? Can we see a stack trace?
List<T>.Clear
is really quite simple. Using Reflector:
public void Clear() {
if (this._size > 0) {
Array.Clear(this._items, 0, this._size);
this._size = 0;
}
this._version++;
}
In the case when the list already empty, that is not going to ever throw an exception. However, if you are modifying the list on another thread, Array.Clear
could throw an IndexOutOfRangeException
exception. So if another thread removes an item from the list then this._size
(the number of items to clear) will be too big.
The documentation doesn't mention any Exception this method throws, your problem is probably elsewhere.
List<T>.Clear
This typically happens if multiple threads are accessing the list simultaneously. If one thread deletes an element while another calls Clear(), this exception can occur.
The "answer" in this case is to synchronize this appropriately, locking around all of your List access.
Edit:
In order to handle this, the simplest method is to encapsulate your list within a custom class, and expose the methods you need, but lock as needed. You'll need to add locking to anything that alters the collection.
This would be a simple option:
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
}