1

I am trying to get a method invoked for each item in a list while passing that method the list item itself. Basically I can do it the drawn out way but was trying to get it in a concise LINQ statement like so:

var urls = html.DocumentNode.SelectNodes("//a[@href]")
             .Select(a => a.Attributes["href"].Value)
             .Where(href => !href.StartsWith("mailto:")) // skip emails, find only url links
             .ToList();
            //.ToList().ForEach(href => getWEbData(href.ToString ()));

            foreach (string s in urls) {
                getWEbData(s);
            }

I could not figure out how to get the .ForEach() in to the LINQ shorthand or if its possible.

kacalapy
  • 9,806
  • 20
  • 74
  • 119
  • 1
    Possible duplicate of [LINQ equivalent of foreach for IEnumerable](http://stackoverflow.com/questions/200574/linq-equivalent-of-foreach-for-ienumerablet) – horns Oct 14 '15 at 20:24

4 Answers4

1

You can't. LINQ functions are designed to not cause side effects. ForEach is designed to cause side effects. Hence, there is no ForEach LINQ function.

See "foreach" vs "ForEach" by Eric Lippert

horns
  • 1,843
  • 1
  • 19
  • 26
1

Don't try to use foreach with Linq. Id adds no values and makes it harder to debug. You can embed the query in the foreach call like so:

foreach (string s in html.DocumentNode
                         .SelectNodes("//a[@href]")
                         .Select(a => a.Attributes["href"].Value)
                         .Where(href => !href.StartsWith("mailto:"))) 
{
    getWEbData(s);
}

Note that ToList() is unnecessary (whether you do the query inside or outside of the foreach)

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • looks identical to the for each i have after the generation of the href – kacalapy Oct 14 '15 at 20:24
  • @kacalapy I just inlined the query and took off the `ToList()` using `List.Foreach()` adds no value - all it's doing is iterating internally the same way `foreach` does. – D Stanley Oct 14 '15 at 20:29
0

There is no LINQ .ForEach method, but you can easily write your own:

public static class IEnumerableExtensions {
   public static void ForEach<T>(this IEnumerable<T> pEnumerable, Action<T> pAction) {
      foreach (var item in pEnumerable)
         pAction(item);
   }
}

and then

html
.DocumentNode
.SelectNodes("//a[@href]")
.Select(a => a.Attributes["href"].Value)
.Where(href => !href.StartsWith("mailto:")) // skip emails, find only url links
.ForEach(href => getWEbData(href.ToString ()));

or slightly better (although I think href may already be a string):

...
.Select(href => href.ToString())
.ForEach(getWEbData);

Although, as others have indicated, just because you can doesn't necessarily mean you should, but that was not your question.

Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
0

you can use foreach with Linq but its better to have a constructor i.e. in Select statement take a new class object and make a parameterized constructor of that class an in the constructor you can do whatever you want it is one of the easiest and efficient way.

Varun Vasishtha
  • 461
  • 2
  • 9