views:

2489

answers:

2

EDIT

For reference, here's the blog post which eric referrrred to in the comments

http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

ORIG

More of a curiosity I suppose but one for the C# Specification Savants...

Why is it that the ForEach() clause doesn't work (or isn't available) for use on IQueryable/IEnumerable result sets...

You have to first convert your results ToList() or ToArray() Presumably theres a technical limitation to the way C# iterates IEnumerables Vs. Lists... Is it something to do with the Deferred Execution's of IEnumerables/IQuerable Collections. e.g.

var userAgentStrings = uasdc.UserAgentStrings
    .Where<UserAgentString>(p => p.DeviceID == 0 && 
                            !p.UserAgentString1.Contains("msie"));
//WORKS            
userAgentStrings.ToList().ForEach(uas => ProcessUserAgentString(uas));         

//WORKS
Array.ForEach(userAgentStrings.ToArray(), uas => ProcessUserAgentString(uas));

//Doesn't WORK
userAgentStrings.ForEach(uas => ProcessUserAgentString(uas));
+6  A: 

It's perfectly possible to write a ForEach extension method for IEnumerable<T>.

I'm not really sure why it isn't included as a built-in extension method:

  • Maybe because ForEach already existed on List<T> and Array prior to LINQ.
  • Maybe because it's easy enough to use a foreach loop to iterate the sequence.
  • Maybe because it wasn't felt to be functional/LINQy enough.
  • Maybe because it isn't chainable. (It's easy enough to make a chainable version that yields each item after performing an action, but that behaviour isn't particularly intuitive.)

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    if (source == null) throw new ArgumentNullException("source");
    if (action == null) throw new ArgumentNullException("action");

    foreach (T item in source)
    {
        action(item);
    }
}
LukeH
point taken, but the question was more in reference to why it's not available out of the box... i.e. Array has a static `ForEach()` method. List has one... Why don't IEnumerable/IQueryable
Eoin Campbell
I guess we'll have to wait for Eric's blog post to find out the real answer ;)
LukeH
Your guesses are remarkably similar to my posting.
Eric Lippert
+13  A: 

What an amazing coincidence, I just now wrote a blog article about this very question. It will be was published May 18th. There is no technical reason why we (or you!) couldn't do this. The reasons why not are philosophical. See my blog next week for my argument.

Eric Lippert
I was actually reading your mind Eric, but wanted to beat you to the punch ;) Cheers for the info, will check out the blog link next week. Cheers...
Eoin Campbell
lol... mark as answer!!!!
vidalsasoon
@Eric - I don't get why you don't think it's useful when chaining a bunch of methods together like .Where(...).Select(...).ForEach(...);
Micah
@Micah: Which reason I gave in my article was unclear? I do believe it is useful. I believe that it is *insufficiently useful* to warrant doing the work, and that it encourages bad coding practices such as embedding side effects in what logically look like queries. Either reason alone is enough to not add this method.
Eric Lippert