How to use conditional in List.ForEach()?

835 views Asked by At

I need to remove items from the HttpSession collection. In the following code, myList contains the same items as Session. If there are items in myList/Session that are not in itemsToRemove, they should be deleted from the session collection.

However, I'm not sure what the lambda syntax should look like. The following isn't correct.

myList.ForEach(x => !itemsToRemove.Contains(x) { Session.Remove(x) });

Any ideas how I can use a lambda expression to put everything on one line to accomplish this task?

Also, is there a way to avoid creating the intermediate list (myList)? I'm only doing that because I can't remove items from Session while iterating through it.

2

There are 2 answers

5
abatishchev On BEST ANSWER

The most naïve way:

myList.Where(x => !itemsToRemove.Contains(x)) // LINQ extension method
      .ToList()                                                                 <----
      .ForEach(x => Session.Remove(x));       // List<T> method so this is required |

Also you can use this:

mystList.Except(itemsToRemove)
        .ToList()
        .ForEach(x => Session.Remove(x));

But to use ForEach the underlying type should be List<T> so you need to call ToList() first. What causes 1 excess enumeration of the whole collection.

I would do this instead:

foreach (var x in mystList.Except(itemsToRemove))
{
    Session.Remove(x)
}

This will minimize the number of enumerations.

0
Oblivious Sage On

First off, abatischev's answer is excellent. It's ideal from both a performance perspective and a readability perspective. If, however, you really want to cram all the functionality into one statement (which I don't recommend), you could try the following:

Session.OfType<string>()
       .Except(itemsToRemove)
       .ToList()
       .ForEach(x => Session.Remove(x));

As abatischev metnioned, the ToList() call costs you an extra enumeration through the collection, which could have a non-trivial performance impact if the collection has a large number of elements in it. However, it means the ForEach() call iterates over a newly created List<string>, which fills the role of your myList and lets you remove items from the Session (since you're iterating through that temporary list, rather than the Session).

(Note that I haven't worked with HttpSessionState objects myself, merely looked at their MSDN article. You may need to replace the string generic type with something else if strings aren't what HttpSessionState holds.)