Изменение списка внутри цикла foreach

У меня есть подобная конструкция (но намного сложнее):

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;, прежде чем он заметит?

Ответы

Ответ 1

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

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

}

Ответ 2

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

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

foreach(var item in list.ToList())

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

Ответ 3

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

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

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();