Glenn Block

Sponsors

The Lounge

News

  • View Glenn Block's profile on LinkedIn

    Me

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
ForEach, a simple but very useful extension method

This evening I was writing some code (Yay!) for an Xml based MEF catalog I am prototyping. I came across the need to invoke a set of methods on an IEnumerable<T> that was returned from a LINQ to XML query. Unfortunately no such animal exists on IEnumerable.

It took me < 5 mins to write this

   1: public static class IEnumerableUtils
   2: {
   3:       public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
   4:       {
   5:         foreach(T item in collection)
   6:           action(item);
   7:       }
   8: }

Any questions?


Posted 08-19-2008 12:46 AM by Glenn Block
Filed under: ,

[Advertisement]

Comments

Neil Barnwell wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 4:44 AM

I just wrote this in a Main method:

           List<string> items = new List<string>();

           items.Add("Item 1");

           items.Add("Item 2");

           items.Add("Item 3");

           items.ForEach(s => Console.WriteLine(s));

Is this not what you want?  I'm running VS 2008 on .NET 3.5.

Łukasz Podolak wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 5:24 AM

No Neil, List<T> is probably too much what he wants.

I also was wondering why the ForEach method was put inside List<T> and not IEnumerable<T> ?

Neil Barnwell wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 5:57 AM

Ahh, of course.  He only has the IEnumerable interface and my example was getting ForEach from List<T>.

Gosh, I amaze myself with my own stupidity sometimes.

Sidar Ok wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 7:50 AM
Kent Boogaart wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 7:50 AM

There's also no equivalent on System.Linq.Enumerable, which has irked me on several occasions.

Jimmy Bogard wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 8:23 AM

Ah! And don't forget ForEach's cousin, with an index:

public static void Each<T>(this IEnumerable<T> items, Action<T, int> action)

{

int i = 0;

foreach (var item in items)

{

action(item, i++);

}

}

Calvin wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 9:08 AM

Beautiful. I'm a fan of anything that makes C# act more like Ruby.

Peter Ritchie wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 9:12 AM

I've often wondered why a ForEach wasn't added for IEnumerable<T>.  It's very handy on List<T>...

Chris wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 9:30 AM

Took me less than 5 seconds to google an existing solution :)

davesquared.blogspot.com/.../ienumerable-and-foreach.html

Yoshi Carroll wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 9:41 AM

I've been (over?)thinking about this for a while now and have currently settled on using ToList().Foreach() instead. What bothers me about the implementation you show is that it breaks the conventions of Linq extension methods in that it's not chainable, and it's not lazy. So, while it's possible to do .Where().Select().Foreach(), its not possible to do .Where().Foreach().Select().

This is obviously by design and it works as you needed it to but it feels a bit ambiguous to me. I tried to think of another name for it, something that would communicate the distinction, but nothing felt right.

Using .ToList().Foreach() is more explicit in what the intention is, but it has an extra method in the chain, and it's enumerating the collection twice, so I'm not much happier with it either.

Am I just overworking this idea?

Kent Boogaart wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 11:44 AM

Ugh, just realised how stupid my comment was. It's exactly what you were talking about. Sleep.

In summary, enumerating an enumerable seems like the perfect thing for System.Linq.Enumerable to do. And yet it doesn't.

Bryan Reynolds wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 12:01 PM

Inconsistencies. ugh.

Kelly Leahy wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 12:47 PM

I think the reason ForEach wasn't added to IEnumerable<T> (not via extension methods, but to the interface itself) was that doing so would require reimplementation of this 'algorithm' by anyone who implements IEnumerable<T>.  That would be painful at best and error-prone at worst.

Bill wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 3:18 PM

I like this as a better implementation:

public IEnumerable<TSource> ForEach(this IEnumerable<TSource> collection, Action<TSource> action) {

   foreach(var item in collection) {

       action(item);

       yield return item;

   }

}

Glenn Block wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 3:37 PM

@Bill

I can see the value in, though I would have adifferent name then. foreach in fx by itself only yields if I add the yield statement.

Glenn

Glenn Block wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 3:38 PM

@Kelly

Sure, but to keep with how LINQ extensions were handled, it would have been added via an extension method to the interface ;)

Chris Tavares wrote re: ForEach, a simple but very useful extension method
on 08-19-2008 6:46 PM

I suspect the reason that this didn't exist before is that you can't use it from VB. VB only support lambda expressions, while the foreach method requires a lambda *statement*.

Zack Owens wrote re: ForEach, a simple but very useful extension method
on 08-21-2008 3:48 PM

Any reason you didn't check for nulls?

Greg Beech wrote re: ForEach, a simple but very useful extension method
on 08-23-2008 11:35 AM

My assumption as to why the Enumerable class doesn't provide a ForEach extension method is because there are a number of valid implementations, using either deferred or immediate execution. I wrote more about this a couple of months back: gregbeech.com/.../why-doesn-t-system-linq-enumerable-have-a-foreach-extension-method.aspx

wekempf wrote re: ForEach, a simple but very useful extension method
on 08-25-2008 4:03 PM

Both Yoshi Carroll in the comment above, and Greg Beech in his linked post comment that Linq uses deferred execution and chaining.  That's simply not true.  Some parts of Linq follow this, but not all.  Just one example is Average, which is neither chainable nor does deferred execution.  I can't begin to guess why ForEach was left out, but it seems obvious that's not why.

Greg Beech wrote re: ForEach, a simple but very useful extension method
on 08-26-2008 7:02 AM

I left a full response on my blog post (where wekempf also posted a comment). The essence is that not all LINQ operations are chainable or deferred, but all operations that are chainable are also deferred, and vice versa. As it isn't clear whether ForEach should be chainable, it isn't clear whether it should be deferred.

wekempf wrote re: ForEach, a simple but very useful extension method
on 08-26-2008 9:19 AM

I posted on your blog as well, but the gist of my post is that to those who have used other functional languages, it is clear that ForEach should not be chainable.

Pensando en asíncrono wrote Update-Select en un DataTable con LINQ
on 09-11-2008 6:33 PM

Últimamente ya no escribo nada, estoy totalmente inmerso en el mundo LINQ con el C# 3.0 y LINQ de Octavio

vtortola wrote Update-Select en un DataTable con LINQ
on 09-11-2008 6:33 PM

Últimamente ya no escribo nada, estoy totalmente inmerso en el mundo LINQ con el C# 3.0 y LINQ de Octavio

Octavio Hernandez wrote re: ForEach, a simple but very useful extension method
on 09-12-2008 6:33 AM
Glenn, This extension method has the potential problem that it may lead developers to think that they can universally use it in order to update each member of a collection. For instance, given class Person { public string Name { get; set; } public int Age { get; set; } public override string ToString() { return Name + "(" + Age + ")"; } } you could do List list1 = new List { new Person() { Name = "ann", Age = 23 }, new Person() { Name = "barbara", Age = 28 }, new Person() { Name = "celia", Age = 27 }, }; list1.ForEach( p => { p.Age++; }); and this will increment the age of each Person in the collection. But this "technique" will not work for collections of any value type, and not even of string, which is a reference type!
Sobre C#, LINQ y algo más... wrote Observaciones con respecto a un método extensor ForEach<T>
on 09-14-2008 8:22 AM

Recientemente, Valeriano Tórtola publicó un excelente post en el que mostraba la utilización de un método

Fique por dentro Extensor » Blog Archive » ForEach, a simple but very useful extension method - Glenn Block wrote Fique por dentro Extensor &raquo; Blog Archive &raquo; ForEach, a simple but very useful extension method - Glenn Block
on 01-17-2009 12:47 AM

Pingback from  Fique por dentro Extensor  &raquo; Blog Archive   &raquo; ForEach, a simple but very useful extension method - Glenn Block

Add a Comment

(required)  
(optional)
(required)  
Remember Me?