Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.92/13: Рейтинг темы: голосов - 13, средняя оценка - 4.92
0 / 0 / 0
Регистрация: 30.11.2014
Сообщений: 5

Перечисление изменяемой коллекции

30.11.2014, 13:40. Показов 2830. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.

Имеется следующая ситуация:
Есть коллекция классов Dictionary<int, Class>

Штатная ситуация - класс удаляется из этой коллекции
Получается, что коллекция меняется (удаляется объект) во время перечисления (получение объектов по условию)

В результате:
если идет перечисление с использованием enumerator (foreach) - ошибка изменения коллекции;
если перечисление в цикле while по Count с доступом по индексу - ошибок нет, но получается пропуск элементов из-за из сдвига, но четко определенного числового индекса.

Лочить коллекцию во время перечисления - не по нраву, т.к. удаление элементов вполне штатная ситуация. И не хочется оттягивать сборку удаленного элемента в мусор.

В связи с этим вопрос: можно ли (и как) реализовать перечисление изменяемой коллекции примерно так:
Итератор указывает на определенный элемент коллекции, например на 15-й из 25 элементов. Удаляется 16-й элемент, коллекция сдвигается, теперь размер - 24 элемента и следующий за 15-м 17-й элемент, на который просто сдвигается итератор. В случай удаления уже пройденного элемента - аналогичная ситуация, т.е. итератор просто переходит на следующий элемент, проверяя next'ом последний элемент коллекции?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.11.2014, 13:40
Ответы с готовыми решениями:

Цикл по изменяемой коллекции
В общем такая ситуация. У меня есть 2 списка: первый содержит несколько уникальных адресов, второй список так называемая база данных...

Как удалить элемент из коллекции, во время перебора этой коллекции foreach?
Прив. Смотрите что. Есть сервер, на нем 2 класса - Server &amp; ClientConnection. При подключении нового клиента в Server создается новый...

Сделать сортировку коллекции вместо создания новой коллекции с передачей IOrderedEnumerable<T>
Есть: SortableObservableCollection&lt;T&gt; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using...

8
 Аватар для m0nax
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
30.11.2014, 14:07
накопить элементы которые надо удалить в список, потом циклом по этому списку и удалять
0
0 / 0 / 0
Регистрация: 30.11.2014
Сообщений: 5
30.11.2014, 14:30  [ТС]
Это решение "от обратного".
Но хотелось бы сделать именно перечисление изменяемой коллекции, разово реализовать такую коллекцию и применять.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
30.11.2014, 16:23
Цитата Сообщение от ras-oz Посмотреть сообщение
можно ли (и как) реализовать перечисление изменяемой коллекции
Вот примерно что я накидал по вашему вопросу. Особо не вдавался, может где что-то и вылезет не так, но вроде бы работает. Пробуйте.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace TaskCollectionProject {
    class Program {
        static void Main(string[] args) {
            ClassCollection classCollection = new ClassCollection {
                new Class{ID = 1},
                new Class{ID = 2},
                new Class{ID = 4},
                new Class{ID = 3}
            };
 
            foreach (Class c in classCollection.GetAllClasses(1)) {
                Console.WriteLine(c);
            }
            Console.ReadLine();
        }
    }
    class Class {
        public int ID { get; set; }
        public override string ToString() {
            return string.Format("ID: {0}", ID);
        }
    }
    class ClassCollection:IEnumerable<Class> {
        private List<Class> classes = new List<Class>();
 
        public IEnumerable<Class> GetAllClasses(int key) {
            for (int i = 0; i < classes.Count; i++) {
                if (classes[i].ID == key) {
                    classes.RemoveAt(i);
                }
                yield return (i >= classes.Count) ? null : classes[i];
            }
        }
        public void Add(Class c) {
            classes.Add(c);
        }
 
        IEnumerator<Class> IEnumerable<Class>.GetEnumerator() {
            return classes.GetEnumerator();
        }
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return classes.GetEnumerator();
        }
    }
}
1
0 / 0 / 0
Регистрация: 30.11.2014
Сообщений: 5
30.11.2014, 21:38  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Вот примерно что я накидал по вашему вопросу. Особо не вдавался, может где что-то и вылезет не так, но вроде бы работает. Пробуйте.
Спасибо, но немного не то, что нужно.
Изменил код как планировал использовать: добавил метод ClassCollection. RemoveElementAt(int )
и удаляю элемент в процессе перечисления.
И выходит ошибка в выходных данных, как и при использовании while, т.к. итератором в приведенном примере используется переменная, а количество "пляшет" от Count'а
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        static void Main(string[] args)
        {
            ClassCollection classCollection = new ClassCollection 
            {
                new Class{ID = 1},
                new Class{ID = 2},
                new Class{ID = 4},
                new Class{ID = 3}
            };
 
            foreach (Class c in classCollection.GetAllClasses())
            {
                // Эмуляция удаления данных в процессе перечисления
                if (c.ID == 4)
                {
                    classCollection.RemoveElementAt(1);
                }
                Console.WriteLine(c);
            }
            Console.ReadLine();
        }
    }
    class Class
    {
        public int ID { get; set; }
        public override string ToString()
        {
            return string.Format("ID: {0}", ID);
        }
    }
    class ClassCollection : IEnumerable<Class>
    {
        private List<Class> classes = new List<Class>();
 
        public IEnumerable<Class> GetAllClasses()
        {
            for (int i = 0; i < classes.Count; i++)
            {
                yield return (i >= classes.Count) ? null : classes[i];
            }
        }
        public void Add(Class c)
        {
            classes.Add(c);
        }
 
        public void RemoveElementAt(int i)
        {
            classes.RemoveAt(i);
        }
 
        IEnumerator<Class> IEnumerable<Class>.GetEnumerator()
        {
            return classes.GetEnumerator();
        }
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return classes.GetEnumerator();
        }
Вывод:
ID 1
ID 2
ID 4

Вполне резонный, исходя из кода, но неверный исходя из идеи, должен быть полным
ID 1
ID 2
ID 4
ID 3
Т.е. элемент удаляется тот, который уже перечислен.

А хотелось бы чтобы итератор просто перешел на следующий элемент, не обращая внимание на текущий Count.
Вообще, средствами C# это возможно?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
30.11.2014, 21:51
Цитата Сообщение от ras-oz Посмотреть сообщение
И выходит ошибка в выходных данных
Естественно у вас будет ошибка. Вы разве не видите разницы? Я удаляю элемент внутри итератора, а вы снаружи. Если я верно вас понял, то нужно сначала вывести элемент, а потом удалить, так? Тогда мой код немного подкорректировать, и все должно получиться.
0
0 / 0 / 0
Регистрация: 30.11.2014
Сообщений: 5
30.11.2014, 23:07  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Естественно у вас будет ошибка. Вы разве не видите разницы? Я удаляю элемент внутри итератора, а вы снаружи. Если я верно вас понял, то нужно сначала вывести элемент, а потом удалить, так? Тогда мой код немного подкорректировать, и все должно получиться.
Разницу как раз я вижу. Я описал в начале темы нужную идею итератора.
И наверное не удивительно, что я подогнал код под нужный мне вариант.

Цитата Сообщение от ras-oz Посмотреть сообщение
Штатная ситуация - класс удаляется из этой коллекции
Получается, что коллекция меняется (удаляется объект) во время перечисления (получение объектов по условию)
Может не совсем понятно, что удаление происходит "снаружи", из другого потока.
Структура проекта не слишком удачная, досталась в таком виде.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
30.11.2014, 23:59
Цитата Сообщение от ras-oz Посмотреть сообщение
Структура проекта не слишком удачная, досталась в таком виде.
Возможно, стоит ее пересмотреть, если все так неудачно, чем пытаться переделать то что есть?
0
0 / 0 / 0
Регистрация: 30.11.2014
Сообщений: 5
01.12.2014, 00:16  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Возможно, стоит ее пересмотреть, если все так неудачно, чем пытаться переделать то что есть?
Кто бы сомневался, что обязательно будет такой совет, тем более, что я его спровоцировал.

Значит, как я понимаю, идеи по теме кончились (вернее толком и не начинались).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.12.2014, 00:16
Помогаю со студенческими работами здесь

Доступ из элемента коллекции к другим элементам коллекции
Подскажите как получить данные из другого элемента коллекции? В приведенном примере необходимо реализовать метод который бы брал значение...

Рекусивное перечисление
Для бинарного дерева создаю перечислитель. Есть рекурсивная функция обхода узлов. Возможно ли задание функции GetEnumerator() рекурсивным...

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

Перечисление в поле таблицы по связи
Есть две таблицы (Первая-Виды работ, там ид и название, а вторая Здания там ид здания и виды работ). Стоит связь между ними 1 ко многим по...

Удаление элемента коллекции в коллекции коллекции )
Есть коллекция (к1), в ней элементы + коллекция (к2), Так вот в к2 тоже есть элементы, и из к2 надо удалить элемент. к1 отображается на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор значений справочника
Maks 21.03.2026
Установка программного отбора значений справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru