Loading...

Във форума е въведено ограничение, което позволява на потребителите единствено да разглеждат публикуваните въпроси.

VladoGenov avatar VladoGenov 45 Точки

[LISTS] - Exercise - 07-Count Numbers

Здравейте, колеги!
В едно от решенията на задачата за упражнение от List - Problem: Count Numbers (slide 19):
Read a list of integers in range [0…1000] and print them in ascending order along with their number of occurrences

Срещам следния проблем: В хода на изпълнението в ред 22 от следния код: http://pastebin.com/JjCeEvbA
при четенето на 2-я елемнт от списъка inputL, цикъла foreach ми дава следната грешка:
System.InvalidOperationException was unhandled
  HResult=-2146233079
  Message=Collection was modified; enumeration operation may not execute.
  Source=mscorlib
  StackTrace:
       at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
       at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
       at System.Collections.Generic.List`1.Enumerator.MoveNext()
       at _07_Count_Numbers.CountNumbers.Main(String[] args) in D:\...\16-Lecture-List_and_Matrics\07-Count Numbers\CountNumbers.cs:line 38
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:


Въпросът ми е: каква е причината цикъла foreach да дава грешка при четенето на втория елемент???
(P.S.: Задачата съм я решил по друг начин, въпросът ми не е свързан с намиране на решение!!!)

Тагове:
0
Programming Basics
RoYaL avatar RoYaL Trainer 6849 Точки

Здравей,

Списъците са референтен тип данни. Присвояването на една променлива от тип списък в друга променлива не предизвиква копиране на списъка, а само създаване на две променливи, които сочат на едно и също място в паметта. Съответно tempL и inputL сочат към едни и същи елементи.

Когато обходиш тези елементи (независимо дали през inputL или tempL) чрез foreach, нямаш право да правиш промяна по тях. В твоя случай обхождаш поредицата, след това я обхождаш отново (през tempL, но тя е същата) и я променяш ( tempL.RemoveAt(j);  ). Което предизвиква Collection was modified.

Вариантът е да копираш всеки един елемент по отделно и да го присвоиш в новата колекция. Може да стане през конструктора на списъка, също така може би най-разбираемо ще ти е да минеш с foreach през inputL и всеки един елемент да го Add() в tempL.

Поздрави,

Иван

5
10/04/2016 21:13:24
VladoGenov avatar VladoGenov 45 Точки

Благодаря Иван ( RoYaL ) за изчерпателния и полезен отговор!
Важно беше уточнението "Присвояването на една променлива от тип списък в друга променлива не предизвиква копиране на списъка", и че така указателите и на двете променливи ( tempL и inputL ) сочат към едно и също място в паметта!
Чрез изчерпателния отговор на Иван и с предложението на колегата  ArmenPotourlyan от предходния коментар:

List<int> tempL = new List<int>(inputL);

проблема се реши и най-важното осмислих същността на копирането/създаването на списъци, а предполагам е същото и с масивите.

Благодаря Ви отново колеги за отговорите!
Благословения!

1
petar.dimitrov.86 avatar petar.dimitrov.86 450 Точки

Много полезна информация, благодарим на RoYaL и ArmenPotourlyan за изчерпателните отговори. Това е наистина нещо, което човек може да обърка, когато не е свикнал или е под стрес на изпита :D Като допълнение само, това, което аз правя за да съм най-сигурен че ми се добавят елементите на един списък в друг, е директно да ползвам .AddRange(иметонаоригиналниясписък).

Или за този случай:

List<int> tempL = new List<int>();

tempL.AddRange(inputL);

Прави абсолютно същото като List<int> tempL = new List<int>(inputL); но лично за мен по-добре мога да се ориентирам като чета кода кой списък какви елементи има.

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.