Neurodefekt
Neurodefekt

Reputation: 909

Combined actions in LINQ for IEnumerable/List?

I want to delete every file from a directory that matches a certain condition, but I also want the items to be removed from my list (or IEnumerable) (because I want to work with that list later and don't want any items in it that are not existing anymore on the filesystem!)

An easy approach would be to gather every item that matches a certain condition into a list and then looping through the temporary list and deleting both the file and listitem from the original list. But I'd appreciate to see a solution where both of the tasks are done in one step, without creating a filtered temporary list first.

// non-sense code example
lstFiles.ForEach(x => x.CreationTime < __now.AddDays(maxAge * -1), x => x.Delete())
    .Remove(x);
// or...
newList/IEnumerable = lstFiles.Where(x => x.CreationTime < __now.AddDays(maxAge * -1), x.Delete()).RemoveAll(x)

Alternate question: Can I make a list of files where every item is added that (does not) match the condition and every else gets delete? Something like an addional .WhereNot(x => x.Delete())?

or...

IEnumerable<FileInfo> cleanedList =
    (from files in directory.EnumerateFiles()
     where files.CreationTime < __now.AddDays(maxAge * -1)
     wherenot files.Delete()
     select files)

Upvotes: 0

Views: 195

Answers (3)

Brent Stewart
Brent Stewart

Reputation: 1840

Just make your Delete() method return a bool and then you can use:

lstFiles.RemoveAll(x => x.CreationTime < _now.AddDays(maxAge * -1) && x.Delete());

If the first part of the && statement fails, then the second part will not be evaluated, so deletes will only happen on the files who match the criteria.

This has the added benefit of when a delete fails it will not remove the file from your list.

Upvotes: 3

polkduran
polkduran

Reputation: 2551

You can use different approach: Instead of having a List you can have an ObservableCollection, attach a handler to the event CollectionChanged and every time an item is deleted you delete the associated file.

collection.CollectionChanged += ContentCollectionChanged;
[...]
public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Remove)
    {
        foreach(var file in e.OldItems)
        {
            //Removed file
        }
    }
}

This way you can only need to handle the elements to remove in your collection.

Upvotes: 0

Judah Gabriel Himango
Judah Gabriel Himango

Reputation: 60011

If you want to do multiple operations while keeping the chaining operation, you can use Microsoft's Interactive Extensions (IX) and the .Do and .ForEach extensions.

lstFiles
   .Where(x => x.CreationTime < __now.AddDays(maxAge * -1))
   .Do(x => x.DoThing1())
   .Do(x => x.DoThing2())
   .ForEach(x => x.Remove());

Upvotes: 0

Related Questions