3

does List Sort modify the collection?

I think it must as I get a "System.InvalidOperationException: Collection was modified; enumeration operation may not execute." exception on another thread.

In my multi-threaded app all threads I thought were just reading the collection BUT one thread does a sort.

Thanks

CodingHero
  • 2,865
  • 6
  • 29
  • 42
  • 3
    Sorting a collection shouldn't modify the individual elements, but it will obviously modify the *collection*. – Graham Clark Mar 25 '12 at 15:12
  • But will it cause a modified collection exception? – CodingHero Mar 25 '12 at 15:13
  • look at this question - http://stackoverflow.com/questions/604831/collection-was-modified-enumeration-operation-may-not-execute – Dor Cohen Mar 25 '12 at 15:14
  • @CodingQuant: Yes, because it's modifying the collection. – Jon Skeet Mar 25 '12 at 15:16
  • @CodingQuant If an Iterator is going through a collection and it gets modified, it will throw a "modified collection" exception. This makes sense doesn't it? If you've got a collection of items and you're looking through them one-by-one, it's going to be quite confusing if someone else comes along and re-orders them! – Graham Clark Mar 25 '12 at 15:18

2 Answers2

9

Yes, Sort is in-place, if that's what you mean, and it will certainly invalidate any iterators.

If you want to see a sorted "view" of the collection, you can use LINQ's OrderBy operator, which doesn't modify the existing collection but returns a sequence which contains the elements from the original collection, but in the given order.

So for example, instead of:

// I want to print out the list of names, sorted...
names.Sort();
foreach (string name in names)
{
    Console.WriteLine(name);
}

You could use:

foreach (string name in names.OrderBy(x => x))
{
    Console.WriteLine(name);
}

Another alternative is just to sort it once when you first populate the list, before anything starts iterating over it - that's the only modification required, and if the sort order won't change (e.g. due to modifications to the objects referred to in the list) then it would make sense to just do it once.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • A bit of additional info, what I've found out: `Sort()` invalidates the iterator, but `Sort(Comparison comparison)` does not. At least calling `Sort((a,b) => a.CompareTo(b))` on a list of integers doesn't throw the InvalidOperationException when iterating through this list from another thread. – BalintPogatsa May 06 '22 at 11:10
  • 1
    @BalintPogatsa: Even if it happens not to in some situations, I would *definitely* not rely on that unless it's documented somewhere. – Jon Skeet May 06 '22 at 11:48
3

Yes the List<T>.Sort method does indeed sort the collection in place and hence modifies the collection. If you want instead to get a new collection which is sorted that doesn't modify the original then use the OrderBy extension method.

List<int> theList = ...;
theList.Sort();  // In place mutating sort. Has a void return
List<int> sorted = theList
  .OrderBy(Comparer<int>.Default)
  .ToList();
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454