Как лучше всего удалить элементы списка в цикле в C#

данный код:

var AllItems = new List<CartItem>();

using(var db = new MainContext())
{
    foreach (var item in AllItems)
    {
        if (!db.tblStoreItems.Where(i => i.ID == item.ItemID).Any())
        {
            AllItems.Remove(item);
        }
    }
}

Это лучший способ удалить элемент из объекта списка в цикле?

3 ответов


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

так как ваша основная коллекция является List<T>, вы должны использовать RemoveAll метод, который принимает предикат. Вы также должны упростить свой запрос следующим образом:

AllItems.RemoveAll(item => !db.tblStoreItems.Any(i => i.ID == item.ItemID));

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

лучше всего использовать старую моду для-loop в обратном порядке

using(var db = new MainContext()) 
{ 
    for(int x = AllItems.Count - 1; x >= 0; x--) 
    { 
        var item = AllItems[x];
        if (!db.tblStoreItems.Where(i => i.ID == item.ItemID).Any()) 
        { 
            AllItems.RemoveAt(x); 
        } 
    } 
}

это неправильно (подход OP), как справедливо предложил Стив (путь Стива, вероятно, лучший с точки зрения производительности),

Я предпочитаю хранить 'those to be removed' в отдельный список, то вы можете сделать, например,

AllItems = AllItems.Except(Items2Remove);  

это не лучший способ производительности, но для меня делает вещи чище - вы также можете объединить с перечислением LINQ-например, сделать IEnumerable из списка записей и т. д.

надеюсь, что это помогает EDIT: просто уточнить в соответствии со Стивом ответ