Прохождение через Foreach, когда это может быть изменено? [дубликат]

12
задан sooprise 12 July 2010 в 21:41
поделиться

8 ответов

Вы можете сделать так, это самый простой способ, который я нашел (хочется думать, что я его придумал, хотя это не так ;))

foreach (var Slice in Pizza.ToArray())
{
    if (Slice.Flavor == "Sausage") // each to their own.. would have gone for BBQ
    {
        Me.Eat(Slice);
    }
}

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

Удобно, не правда ли!

(Кстати, ребята, это удобный способ итерации по копии коллекции, с безопасностью потока и удалением времени блокировки объекта: Заблокировать, получить копию ToArray(), снять блокировку, затем выполнить итерацию)

Надеюсь, это поможет!

25
ответ дан 2 December 2019 в 03:38
поделиться

Если вам нужно выполнить итерацию по списку и нужно удалить элементы, повторите итерацию в обратном направлении с помощью цикла for:

// taken from Preet Sangha's answer and modified
for(int i = Pizza.Count-1; i >= 0, i--)
{
    var Slice = Pizza[i];
    if(Slice.Flavor == "Sausage")
    {
        Me.Eat(Slice); //This removes an item from the list: "Pizza"
    }
}

Причина итерации в обратном направлении заключается в том, что при удалении элементов вы не сталкивайтесь с IndexOutOfRangeException, вызванным доступом к Pizza [5] в Pizza, которая имеет только 5 элементов, потому что мы удалили шестой.

Причина использования цикла for заключается в том, что переменная итератора i не имеет отношения к Pizza, поэтому вы можете изменить Pizza без "нарушения" перечислителя

7
ответ дан 2 December 2019 в 03:38
поделиться

Что это за коллекция Pizza? Если это List , вы можете вызвать метод RemoveAll :

Pizza.RemoveAll(slice => string.Equals(slice.Flavor, "Sausage"));
0
ответ дан 2 December 2019 в 03:38
поделиться

Вероятно, самый ясный способ приблизиться к этому - создать список кусочков, которые нужно съесть, а затем обработать его, избегая изменения исходного перечисления в цикле. Я никогда не был поклонником использования для этого индексированных циклов, так как это может быть подвержено ошибкам.

List<Slice> slicesToEat=new List<Slice>();
foreach(var Slice in Pizza)
{
    if(Slice.Flavor == "Sausage")
    {
        slicesToEat.Add(Slice); 
    }
}
foreach(var slice in slicesToEat)
{
    Me.Eat(slice);
}
3
ответ дан 2 December 2019 в 03:38
поделиться

Возможно, измените подпись Me.Eat() на IEnumerable

Me.Eat(Pizza.Where(s=>s.Flavor=="Sausage").ToList());

Это позволит вам выполнить задачу за 1 строку кода.

Тогда ваш Eat() может выглядеть так:

public void Eat(IEnumerable<Slice> remove)
{
    foreach (Slice r in remove)
    {
        Pizza.Remove(r);
    }
}
2
ответ дан 2 December 2019 в 03:38
поделиться

используйте цикл for, а не foreach

for(int i = 0; i < in Pizza.Count(), ++i)
{

    var Slice = Pizza[i];
    if(Slice.Flavor == "Sausage")
    {
        Me.Eat(Slice); //This removes an item from the list: "Pizza"
    }
}
4
ответ дан 2 December 2019 в 03:38
поделиться

Где можно заказать пиццу, у которой кусочки имеют отдельную начинку ? В любом случае ...

Использование Linq:

// Was "Me.Eat()" supposed to be "this.Eat()"?
Pizza
    .Where(slice => slice.Flavor == "Sausage")
    .Foreach(sausageSlice => { Me.Eat(sausageSlice); });    

Первые две строки создают новый список, содержащий только кусочки колбасы. Третий возьмет это новое подмножество и передаст каждый фрагмент в Me.Eat (). {И;} могут быть лишними. Это не самый эффективный метод, потому что он сначала создает копию (как и многие другие предложенные подходы), но он, безусловно, чистый и читаемый.

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

0
ответ дан 2 December 2019 в 03:38
поделиться

Объект «Коллекция» в стиле VB6 допускает модификацию во время перечисления и, кажется, работает разумно, когда такие модификации происходят. Жаль, что он имеет другие ограничения (тип ключа ограничен строками без учета регистра) и не поддерживает универсальные типы, поскольку ни один из других типов коллекций не допускает модификации.

Честно говоря, мне непонятно, почему контракт Microsoft iEnumerable требует, чтобы при изменении коллекции генерировалось исключение. Я бы понял требование о создании исключения, если изменения в коллекции сделают невозможным продолжение перечисления без дурацкости (пропуск или дублирование значений, которые не изменились во время перечисления, сбоя и т. Д.), Но я не вижу причин не делать этого. позволить коллекции, которая могла бы разумно перечислить, сделать это.

0
ответ дан 2 December 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: