-2

After reading a couple of notes that it's better not to lock the whole foreach block, decided to always return a cloned instance of the collection from the enumerator. This is the code that I'm currently using.

https://stackoverflow.com/a/5874474/437393

Then, some code from another thread calls collection.ElementAtOrDefault(collection.Count - 1) and Clone method inside of my collection breaks with exception below. Why and how to make it right?

Destination array is not long enough to copy all the items in the collection. Check array index and length

Collection

private static readonly object _indexLock = new object();

...

public IEnumerator<T> GetEnumerator()
{
  return Clone().GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
  return Clone().GetEnumerator();
}

public List<T> Clone()
{
  var copy = new List<T>(_items.Count);

  lock (_indexLock)
  {
    copy = _items.ToList();
    //_items.ForEach(o => copy.Add(o));
  }

  return copy;
}
Anonymous
  • 1,823
  • 2
  • 35
  • 74
  • Do you use the `_indexLock` to protect all access to the `_items` list from everywhere? – Theodor Zoulias Sep 25 '20 at 04:57
  • @Theodor Zoulias Yes, if I protect `_items` with lock everywhere, everything works fine. Meanwhile, the whole point of this experiment is to use a copy of the collection instead of locking it. – Anonymous Sep 25 '20 at 20:47
  • Could you update your question by providing a minimal example that reproduces this error? – Theodor Zoulias Sep 26 '20 at 03:25

1 Answers1

1

You are accessing _items.Count outside the lock, either remove the call to _items.Count or move it inside the lock:

var copy = new List<T>(_items.Count);
Lev
  • 583
  • 3
  • 15
  • `Count` is a property, not a method. It doesn't cause enumeration. https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs Also, I tried moving it inside, still was getting the same intermittent error. Also, tried to do `return _items.ToList()` without variables and memory allocation, so there was only one line inside `lock`. No changes. – Anonymous Sep 25 '20 at 20:12