Dunken
Dunken

Reputation: 8681

Remove in foreach just before break

I know there are lots of ways to do it much better but I've seen it in existing code and now I'm wondering whether or not this could have any negative side effects. Please note the break right after Remove. Therefore I don't care about the iterator in general, however, I do care about unexpected behavior (-> potential exceptions).

foreach (var item in items)
{
    //do stuff
    if (item.IsSomething)
    {
        items.Remove(item); //is this safe???
        break;
    }
}

Could it also be possible the compiler optimizes something in a way I don't expect?

Upvotes: 3

Views: 513

Answers (4)

Omid Shariati
Omid Shariati

Reputation: 1916

You can't change the list while iterating within foreach.

The underlying collection cannot be modified while it's being enumerated. A standard approach is to keep the items to remove in second list , and then after Items has been enumerated, then remove each item from Items.

Upvotes: 1

tariq
tariq

Reputation: 2258

then u can do this -- its more efficient when dealing with large lists (Assuming entity framework)

var reducedList = items.where(a=>a.IsSomething).toList();
foreach(var item in reducedList)
{
    reducedList.Remove(item);
}

this reduces the foreach loop iterations

Upvotes: -1

Botz3000
Botz3000

Reputation: 39600

The compiler generates a call to Dispose() on the enumerator that is executed in a finally block, but that shouldn't be a problem. If you break right after removing the item, nothing bad should happen, since you don't use the enumerator anymore.

If you want to do it a different way though (for style reasons or whatever), you could do this:

var item = items.FirstOrDefault(i => i.IsSomething);
if (item != null) {
    items.Remove(item);
}

It's also a bit shorter :) (I am assuming here you are using a reference or nullable type in your collection).

Upvotes: 7

Johannes Egger
Johannes Egger

Reputation: 4041

The compiler and everything else which is in touch with your application guarantees SC-DRF (sequential consistency for data-race-free programs), so you won't see the difference between the program you wrote and the program which is executed (which is anything but the same). Assuming items is not shared between multiple threads this is completely safe to write and has no unexpected behaviors others than if you would call Remove outside the loop.

Upvotes: 2

Related Questions