When I read the code inside .NET, more specifically ListBox.cs and ListView.cs , they have two different classes for storing their SelectedItems collections.
ListBox.cs has a SelectedObjectCollection , which has the following elements:
private ListBox owner; private bool stateDirty; private int lastVersion; private int count;
ListView.cs has a SelectedListViewItemCollection , which only has these members:
private ListView owner; private int lastAccessedIndex = -1;
Therefore, looking at this, I assume that we can conclude that the ListBox collection is a valid enumerator that tracks any changes and the number of items in the list. ListView , on the other hand, does not seem to care about this at all and only tracks the current index of the enumerator and just takes a step forward.
So the ListBox throws an exception, since it tracks changes, the ListView does not.
ListBox.cs : ListBox.cs SelectecObjectCollection The GetEnumerator method looks like this:
public IEnumerator GetEnumerator() { return InnerArray.GetEnumerator(SelectedObjectMask); }
And ListView.cs SelectedListViewItemCollection The GetEnumerator method is as follows:
public IEnumerator GetEnumerator() { if (owner.VirtualMode) { throw new InvalidOperationException(SR.GetString(SR.ListViewCantAccessSelectedItemsCollectionWhenInVirtualMode)); } ListViewItem[] items = SelectedItemArray; if (items != null) { return items.GetEnumerator(); } else { return new ListViewItem[0].GetEnumerator(); } }
So, it looks like the ListView returns an array enumerator, which is constant, and the ListBox returns the actual enumerator as a filter of its InnerArray elements.
I know that this is not what you asked for; but itβs always useful to add all elements to a temporary list before iterating through it to remove things, since you may never know how enumerated elements are implemented on the backend, and how they may change in the future.