matiii
matiii

Reputation: 326

C# continue in one line ForEach

Why I can't do that ? How to manipulate code ?

System.IO.Directory.GetFiles(@"..\DATA\data", "*.pdf").ToList().ForEach(item => item.Contains("TOPRINT") ? continue : System.IO.File.Delete(item));

Upvotes: 1

Views: 3078

Answers (4)

Dave Bish
Dave Bish

Reputation: 19656

Linq is designed for operating on sets of data - therefore, all queries must return a set.

You'll have to do something like this, to get a set of the required data:

var filesToDelete = System.IO.Directory
    .GetFiles(@"..\DATA\data", "*.pdf")
    .Where(item => !item.Contains("TOPRINT"));

Then operate on the data-set returned:

foreach(var file in filesToDelete)
    System.IO.File.Delete(file);

Upvotes: 2

xanatos
xanatos

Reputation: 111940

Please, don't try doing what you tried doing, and don't do this:

System.IO.Directory.GetFiles(@"..\DATA\data", "*.pdf")
    .Where(p => p.Contains("TOPRINT"))
    .All(p => { System.IO.File.Delete(p); return true; });

LINQ expressions should be side-effect free. Deleting a file is surely a side effect. The ForEach method of List<T> is conceptually wrong (child of a pre-LINQ era). Transforming an array in a List<T> just to use the ForEach is doubly conceptually wrong. What I wrote at least is only "singly" conceptually wrong. (but it WILL work).

Ah... and do what Dave Bish suggested! foreach is the right place for side-effects!

Just remember that his filesToDelete will be parsed lazily, so if you enumerate it twice in two foreach, the Contains check will be done twice!

This considered, there are many powerful static methods in the Array class. It is a pity no one uses them.

var filesToDelete = System.IO.Directory.GetFiles(@"..\DATA\data", "*.pdf");
filesToDelete = Array.FindAll(filesToDelete, p => p.Contains("TOPRINT"));

Array.ForEach(filesToDelete, System.IO.File.Delete); // or
// Array.ForEach(filesToDelete, p => System.IO.File.Delete(p));            
// or, better,  foreach (var file in filesToDelete) { System.IO.File.Delete(file); }

Upvotes: 1

Damith
Damith

Reputation: 63105

I would add where before ForEach

System.IO.Directory.GetFiles(@"..\DATA\data", "*.pdf")
      .Where(item => !item.Contains("TOPRINT")).ToList()
      .ForEach(f=> System.IO.File.Delete(f));

Upvotes: 0

Frode
Frode

Reputation: 3455

System.IO.Directory.GetFiles(
    @"..\DATA\data", "*.pdf").
    ToList().
    ForEach(
        item => 
        {
            if (item.Contains("TOPRINT"))
                System.IO.File.Delete(item);
        }
    );

or

(from file in System.IO.Directory.GetFiles(@"..\DATA\data", "*.pdf")
 where file.Contains("TOPRINT")
 select file).ToList().ForEach(item => System.IO.File.Delete(item));

Upvotes: 0

Related Questions