Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с обходом и удалением из коллекции 
:(
    Опции темы
Stas123
Дата 29.7.2011, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.11.2009

Репутация: нет
Всего: нет



Хочу удалить из ObservableCollection некоторые элементы, но такой код не работает
Код

foreach(Order o in this.Orders){
                               if(TraderHelper.IsMatched(o) == true){
                                   this.Orders.Remove(o);
                               }

Ошибка такая
System.Reflection.TargetInvocationException: Адресат вызова создал исключение. ---> System.InvalidOperationException: Коллекция была изменена; невозможно выполнить операцию перечисления.
   at System.RuntimeMethodHandle.InvokeMethodFast
Как лучше сделать?
PM MAIL   Вверх
Суровый
Дата 29.7.2011, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 30.4.2009

Репутация: 1
Всего: 2



Цитата

Как лучше сделать?

Можно попробовать начинать каждый раз поиск заново:
Код

bool ok = true;
do
{
    foreach(Order o in this.Orders)
    {
        if(TraderHelper.IsMatched(o))
        {
            this.Orders.Remove(o);
            ok = false;
            break;
        }
    }
}
while(!ok);                          


Добавлено через 2 минуты и 37 секунд
Второй способ - копирование всех "подходящих элементов":
Код

Orders orders;
foreach(Order o in this.Orders)
{
    if(!TraderHelper.IsMatched(o))
        orders.Add(o);
}
this.Orders = orders;


Это сообщение отредактировал(а) Суровый - 29.7.2011, 14:01
PM MAIL   Вверх
Stas123
Дата 29.7.2011, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.11.2009

Репутация: нет
Всего: нет



в первом случае ,если до первого объекта, который нужно удалить, много объектов, то эта чистка будет выполнятся медленно.

Я не уверен в работоспособности второго вариата. Если мы делаем Add(), то ведь НЕ создается комия добавляамеого объекта?
Если не создается, а лишь копируется ссылка, то после "копирования", у меня старая коллекция повиснет в памяти без имени, но чистильшик не удали её т.к. есть ссылки указывающие на неё. Получается памячть будет загромождатся.
PM MAIL   Вверх
AlexNagits
Дата 29.7.2011, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 14.7.2011

Репутация: нет
Всего: нет



Суровый,  smile 

Stas123, обычно делают так:

Код

List<Order> ordersToRemove = new List<Order>();
foreach(Order o in this.Orders)
{
    if(TraderHelper.IsMatched(o))
        ordersToRemove.Add(o);
}

foreach(Order orderToRemove in ordersToRemove)
    this.Orders.Remove(orderToRemove);


Если выглядит громоздко, то можно использовать linq, например так:
Код

IEnumerable<Order> ordersToRemove = this.Orders.Where(o => TraderHelper.IsMatched(o));
foreach (Order orderToRemove in ordersToRemove)
    this.Orders.Remove(orderToRemove);

PM MAIL   Вверх
CYBERDREAM
Дата 1.8.2011, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I think, there4 I am
***


Профиль
Группа: Завсегдатай
Сообщений: 1096
Регистрация: 31.10.2006
Где: CyberLand

Репутация: 11
Всего: 28



Надеюсь ты понял, что в теле foreach коллецию нельзя изменять?
Можно сделать через цикл for. В этом случае можно обойтись без всяких лишних коллекций
Код

            List<Item> mylist =GetItems();

            for (Int32 i = 0; i < mylist.Count;i++ )
            {
                if(mylist[i].IsObsolete)
                {
                    mylist.RemoveAt(i);
                    i--;
                }
            }

//либо
            for(Int32 i=mylist.Count-1;i>=0;i--)
            {
                if (mylist[i].IsObsolete)
                    mylist.RemoveAt(i);
            }



--------------------
Ищем .Net, Java, Javascript разработчиков, Кипр, Лимассол. (знание английского необязательно)
Telegram, skype: kuchuk.artiom
PM MAIL WWW   Вверх
Stas123
Дата 1.8.2011, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.11.2009

Репутация: нет
Всего: нет



CYBERDREAM, сделал почти также как во втором варианте.
Код

int n = this.Orders.Count - 1;
                           for(int i = n; i >= 0; i--){
                               if(TraderHelper.IsMatched(this.Orders[i]) == true){
                                   this.Orders.Remove(this.Orders[i]);
                               }
                           }

PM MAIL   Вверх
CYBERDREAM
Дата 1.8.2011, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I think, there4 I am
***


Профиль
Группа: Завсегдатай
Сообщений: 1096
Регистрация: 31.10.2006
Где: CyberLand

Репутация: 11
Всего: 28



Код

                               if(TraderHelper.IsMatched(this.Orders[i]) == true){
                                   this.Orders.Remove(this.Orders[i]);
                               }

разве нельзя записать как
Код

                               if(TraderHelper.IsMatched(this.Orders[i])){
                                   this.Orders.RemoveAt(this.Orders[i]);
                               }

Orders какого типа?

Это сообщение отредактировал(а) CYBERDREAM - 1.8.2011, 13:48


--------------------
Ищем .Net, Java, Javascript разработчиков, Кипр, Лимассол. (знание английского необязательно)
Telegram, skype: kuchuk.artiom
PM MAIL WWW   Вверх
Exception
Дата 2.8.2011, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 4525
Регистрация: 26.12.2004

Репутация: 29
Всего: 186



Коллекцию нельзя менять, пока ты по ней бегаешь.
Используй LINQ.

Код

var matches = Orders.Where(TraderHelper.IsMatched).ToList();
foreach (var match in matches)
    Orders.Remove (match);


Обрати внимание на вызов ToList: список на удаление вычисляется отдельно, поэтому ошибки не возникает.

Добавлено @ 00:14
Цитата(CYBERDREAM @  1.8.2011,  14:48 Найти цитируемый пост)
Orders какого типа?


В оп-посте написано: Orders это ObservableCollection.

Цитата(AlexNagits @  29.7.2011,  17:35 Найти цитируемый пост)
Если выглядит громоздко, то можно использовать linq, например так:
Код

IEnumerable<Order> ordersToRemove = this.Orders.Where(o => TraderHelper.IsMatched(o));
foreach (Order orderToRemove in ordersToRemove)
    this.Orders.Remove(orderToRemove)


Этот вариант близок к правде, но от тоже меняет коллекцию на ходу. Ты как бы выдираешь почку из-под ног у Where.




Это сообщение отредактировал(а) Exception - 2.8.2011, 00:15
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1211 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.