51
votes

Possible Duplicate:
Why is there not a ForEach extension method on the IEnumerable interface?

EDIT

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

https://ericlippert.com/2009/05/18/foreach-vs-foreach/

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));
2
I'd write ForEach(uac => ProcessUserAgentString(uas)) as ForEach(ProcessUserAgentString).mmx
What's the problem with a conventional for-each loop? foreach (var uas in UserAgentStrings) ProcessUserAgentString(uas);Dario
Theres no problem... Like I said, it was more of a curiousity why the convention was available to use on Arrays/Lists but not on IQueryables/IEnumerables and as Eric Lippert pointed out below, it's a completely philosophical choice by the dev team and not for any technical reasonsEoin Campbell
Here's an alternative idea of how this could be possible: visualstudio.uservoice.com/forums/121579-visual-studio-2015/…HappyNomad

2 Answers

59
votes

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.

15
votes

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);
    }
}