Изменение списка внутри цикла foreach - PullRequest
17 голосов
/ 09 июня 2011

У меня есть конструкция, похожая на эту (но лот более сложный):

var list = new List<string>();

// .. populate list ..

foreach(var item in list)
{
    DoFunction(list);
}

public void DoFunction(List<string> list)
{
    if(someCondition == true)
    {
        // .. modify list in here ..
    }
}

Теперь я понимаю, что невозможно редактировать коллекцию, через которую вы проповедуете, но как изящно выпрыгнуть из цикла, если вам нужно редактировать список (без оператора try catch)? Есть ли способ узнать, был ли список отредактирован? Можете ли вы отредактировать список и быстро break;, прежде чем он заметит?

Ответы [ 3 ]

34 голосов
/ 09 июня 2011

Да, ты можешь сломаться, если ты этого действительно хочешь.Исключение не будет выдано, пока цикл for не попытается получить следующий элемент из списка.

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

foreach(var item in list.ToList())

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

27 голосов
/ 09 июня 2011

Вместо использования конструкции foreach цикл for позволит изменить список.

for (var x = 0; x < list.Count; x++) {

}
3 голосов
/ 09 июня 2011

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

Например, если вам нужно посмотреть на каждый элемент и выбрать между его удалением и оставлениемкак есть, или вставляя элементы после него, вы можете использовать такой шаблон:

IEnumerable<string> butcherTheList(IEnumerable<string> input)
{
    foreach (string current in input)
    {
        if(case1(current))  
        {
            yield return current;
        }
        else if(case2(current))
        {
            yield return current;
            yield return someFunc(current);
        }
        // default behavior is to yield nothing, effectively removing the item
    }
}

List<string> newList = butcherTheList(input).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...