Лучшая практика для перебора коллекции и ее изменения? - PullRequest
1 голос
/ 02 ноября 2011

Я пытаюсь перебрать коллекцию элементов, выполнить действие и затем удалить элемент с текущим индексом.

Способ, которым я реализовал это в настоящее время, выглядит так:

foreach (CormantRadPane pane in GetPanes().ToList())
{
    pane.Clear();
    StateManager.Remove(pane);
    LayoutManager.Instance.RegisteredPanes.Remove(pane);
    Items.Remove(pane);
}

Вызывая ToList, я создаю копию коллекции, но сохраняю ссылку на каждый объект в первой коллекции.Это позволяет мне перебирать возвраты из коллекции GetPanes без «технического» изменения коллекции.

Это явно склонно к серьезным трудностям при обнаружении ошибок.Каков стандартный способ выполнения такой логики чистым способом, но это также более ясно о хитросплетениях происходящего?

Я немного осмотрелся и увидел такие вещи, как использование цикла for ив обратном порядке по списку, но это кажется действительно громоздким.Мои чувства примерно одинаковы: я оставляю второй список «удаляемых» элементов, а затем перебираю этот список после завершения первого цикла, удаляя каждый объект, найденный во втором списке.

Как вы справляетесь с этим?Спасибо.

Ответы [ 3 ]

5 голосов
/ 02 ноября 2011

Вместо текущего подхода вы можете создать переменную и использовать ее, и я предлагаю использовать цикл for для удаления панели, трюк состоит в том, чтобы просто повторить это в обратном порядке:

var panes = GetPanes();
int count = panes.Count;
for(int i= count - 1; i>=0; i--)
{
       pane = panes[i];
       pane.Clear();
       StateManager.Remove(pane);
       LayoutManager.Instance.RegisteredPanes.Remove(pane);
       //Items.Remove(pane);
       Items.RemoveAt(i);
} 

вызов Items.Remove(pane); занимаетO (n) (если есть список), но в случае использования Items.RemoveAt(i); требуется O (1), поэтому ваш текущий подход использует O (n ^ 2), но если вы можете вызвать RemoveAt (index) (у вас есть какой-то списоки они сортируются одинаково) вы можете обработать это в O (n).

0 голосов
/ 02 ноября 2011

То, что вы имеете в виду, это Robust Iterator, но я не верю, что итератор, предоставляемый как в C #, так и в Java, является надежным.

Если все, что вам нужно, это надежно итерировать по List, вы можетереализовать свой собственный Robust Iterator, отслеживая индекс списка.Это может не сработать для коллекций с менее определенным порядком и для некоторых итераций с произвольным доступом, таких как наборы результатов базы данных.

Возможно, другой отвечающий может помочь вам найти способ не требовать надежного итератора в вашем конкретном случае.

0 голосов
/ 02 ноября 2011

Вы можете использовать расширение списка linq, например:

List<Item> items = GetItems(); items.ForEach(i => {i.DoStuff();i.DoStuff2(););}

По крайней мере, это то, что я обычно делаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...