Problem clearing list <T>

I don't know why I have an IndexOutOfRangeException when I clear System.Collections.Generic.List<T> . It makes sense?

 List<MyObject> listOfMyObject = new List<MyObject>(); listOfMyObject.Clear(); 
+2
c # data-structures
source share
3 answers

This usually happens if multiple threads are accessing the list at the same time. If one thread deletes an element and the other calls Clear (), this exception may occur.

In this case, the β€œresponse” should synchronize this, blocking all access to the list.


Edit:

To cope with this, the easiest way is to encapsulate your list in a custom class and expose the methods you need, but block if necessary. You need to add a lock to everything that modifies the collection.

This will 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 } 
+18
source share

Are you sure this 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 several threads accessing the list at the same time? Can I see the stack trace?

List<T>.Clear 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 is already empty, this will never raise an exception. However, if you modify the list in another thread, Array.Clear may throw an IndexOutOfRangeException . Therefore, if another thread removes an item from the list, then this._size (the number of items to clear) will be too large.

+7
source share

The documentation does not mention the exception that this method raises; your problem is probably elsewhere.
List<T>.Clear

+1
source share

All Articles