Ошибка VB.NET For-Each Loop

Столкнулся с проблемой при написании кода для загрузки настроек моего приложения: следующий код выдает ошибку InvalidOperationException:

For Each c As MapInfo In CurrentMaps
    AddMap(c, False)
Next

Отладчик выделяет часть Далее и из страница MSDN об ошибке, похоже, это связано с тем, что коллекция (CurrentMaps) каким-то образом изменилась по сравнению с тем моментом, когда она в последний раз использовала перечислитель (для обработки For Каждый).

Однако не уверен, почему это произошло, поскольку AddMap берет MapInfo ByVal и не касается ввода (поэтому коллекция не изменяется).

Я изменил это на это, которое отлично работает:

For i As Integer = 0 To CurrentMaps.Count - 1
    AddMap(CurrentMaps(i), False)
Next

Они должны функционально работать одинаково, верно? Есть идеи, почему функция Для каждого не работает?

Изменить:

Ах, понял - проблема в том, что я использую CurrentMaps как временную переменную (коллекция, отслеживающая текущие карты), а AddMap обычно используется в приложении для добавления новой карты (что означает как обновление пользовательского интерфейса, так и добавление его в CurrentMaps). ).

Здесь (при загрузке приложения) я просто использую AddMap для обновления пользовательского интерфейса, но подвызов для добавления элемента в CurrentMaps все еще был там, поэтому он действительно модифицировал CurrentMaps.

Всем спасибо за участие!


person amb9800    schedule 20.01.2011    source источник
comment
Что делает AddMap? это когда-либо касалось CurrentMaps?   -  person cHao    schedule 20.01.2011
comment
Второй фрагмент также не будет работать, если CurrentMaps является словарем или отсортированным списком. Отвратительный вид необнаружимого провала.   -  person Hans Passant    schedule 20.01.2011


Ответы (3)


Нет, они не должны работать одинаково. По сути, вы не можете изменить коллекцию во время ее повторения — и похоже, что именно это и происходит.

Из документов List<T>.GetEnumerator():

Перечислитель остается действительным до тех пор, пока коллекция остается неизменной. Если в коллекцию вносятся изменения, такие как добавление, изменение или удаление элементов, перечислитель безвозвратно становится недействительным, и его поведение не определено.

Вы не показали, что делает ваш метод AddMap, но я подозреваю, что он добавляет карту к CurrentMaps, тем самым делая итератор недействительным.

Если бы вы могли предоставить нам больше информации о том, точно что делает AddMap, мы могли бы помочь вам больше. Что означает False?

person Jon Skeet    schedule 20.01.2011
comment
Верно, но если For Each вызывает подпрограмму, которая просто принимает что-то без ссылки на оригинал (ByVal) и логическое значение, нет никаких причин для изменения коллекции. - person amb9800; 20.01.2011
comment
@amb9800: Учитывая то, что происходит, кажется, что AddMap добавляется к той же коллекции, которую вы перебираете. Вы не показали этот код, хотя. - person Jon Skeet; 20.01.2011
comment
Как указано ниже, при повторном просмотре он действительно непреднамеренно изменяет CurrentMaps. Спасибо! - person amb9800; 20.01.2011

Нет, эти функции работают очень по-разному. В первой версии используется шаблон .Net IEnumerable(Of T) + IEnumerator(Of T). Недопустимо изменять коллекцию во время ее перечисления с помощью этого шаблона. Многие типы BCL применяют это требование.

Второй просто использует шаблон count + index. При условии, что границы остаются правильными, законно изменять коллекцию при перечислении с помощью этого шаблона.

Проблема здесь почти наверняка в том, что AddMap косвенно изменяет коллекцию CurrentMaps и, следовательно, вызывает эту ошибку.

person JaredPar    schedule 20.01.2011

А, понял — проблема в том, что я использую CurrentMaps как временную переменную (коллекцию, отслеживающую текущие карты), а AddMap обычно используется в приложении для добавления новую карту (что означает как обновление пользовательского интерфейса, так и добавление его в CurrentMaps).

Здесь (при загрузке приложения) я просто использую AddMap для обновления пользовательского интерфейса, но подвызов для добавления элемента в CurrentMaps все еще был там, так что это действительно было изменение CurrentMaps.

Всем спасибо за участие!

person amb9800    schedule 20.01.2011
comment
Вам следует изменить исходный вопрос и добавить его в качестве дополнительной информации, а не создавать новый ответ. - person Tim Schmelter; 20.01.2011