views:

6555

answers:

18

Inspired by another question asking about the missing Zip function:

Why is there no ForEach extension method in the Enumerable class? Or anywhere? The only class that gets a ForEach method is List<>. Is there a reason why it's missing (performance)?

+1  A: 

Most of the LINQ extension methods return results. ForEach does not fit into this pattern as it returns nothing.

leppie
ForEach uses Action<T>, which is another form of delegate
Slace
Except leppie's right, all the Enumerable extension methods return a value, so ForEach doesn't fit the pattern. Delegates doesn't come into this.
Cameron MacFarland
Slace: Do you have a point with the above statement?
leppie
Just that an extension method doesn't have to return a result, it serves the purpose of adding a way to call a frequently used operation
Slace
Indeed, Slace. So what if it doesn't return a value?
TraumaPony
In functional languages, 'void' generally doesn't exist, so an empty 'unit' is returned. A ForEach method could allow for continuations or some such... at least, that's the way I see it.
Ryan Riley
+15  A: 

ForEach method was added before LINQ. If you add ForEach extension, it will never be called for List instances because of extension methods constraints. I think the reason it was not added is to not interference with existing one.

However, if you really miss this little nice function, you can roll out your own version

public static void ForEach<T>(
    this IEnumerable<T> source,
    Action<T> action)
{
    foreach (T element in source) 
        action(element);
}
aku
The extension methods allow for this. If there is already an instance implementation of a given method name then that method is used instead of the extension method. So you can implement an extension method ForEach and not have it collide with the List<>.ForEach method.
Cameron MacFarland
Cameron, believe me I know how extension methods work :) List inherits IEnumerable so it will be non-obvious thing.
aku
From the Extension Methods Programming Guide (http://msdn.microsoft.com/en-us/library/bb383977.aspx): An extension method with the same name and signature as an interface or class method will never be called. Seems pretty obvious to me.
Cameron MacFarland
Am I talking something different? I think it's no good when many classes have ForEach method but some of them may work differently.
aku
Ah sorry. When you said "interference with existing one" I thought you were suggesting that the extension method would override the local version. Re-reading made me realise we're talking about the same thing. :)
Cameron MacFarland
A: 

Its probably as hinted by an earlier post, in that foreach is supported as a language keyword in C# and VB.NET (and many others)

Most people (myself included) simply write one themselves as needed and appropriate.

chrisb
+3  A: 

I've always wondered that myself, that is why that I always carry this with me:

        public static void ForEach<T>(this IEnumerable<T> col, Action<T> action) {
        if (action == null)
        {
            throw new ArgumentNullException("action");
        }
        foreach (var item in col)
        {
            action(item);
        }
    }

Nice little extension method.

Slace
col could be null... you could check that as well.
David B
Yeah I do check in my library, I just missed it when doing it quickly there.
Slace
I find it interesting that everyone checks the action parameter for null, but never the source/col parameter.
Cameron MacFarland
+30  A: 

There is already a foreach statement included in the language that does the job most of the time.

I'd hate to see the following:

list.ForEach( item =>
{
    item.DoSomething();
} );

Instead of:

foreach(Item item in list)
{
     item.DoSomething();
}

The later is clearer and easier to read in most situation, although maybe a bit longer to type.

However, I must admit I changed my stance on that issue; a ForEach() extension method would indeed be useful in some situations.

Here are the major differences between the statement and the method:

  • Type checking: foreach is done at runtime, ForEach() is at compile time (Big Plus!)
  • The syntax to call a delegate is indeed much simpler: objects.ForEach(DoSomething);
  • ForEach() could be chained: although evilness/usefulness of such a feature is open to discussion.

Those are all great points made by many people here and I can see why people are missing the function. I wouldn't mind Microsoft adding a standard ForEach method in the next framework iteration.

Coincoin
Hmm, good point. The only thing I can think of that counters this is the fact that List<> also has a ForEach method. Unfortunately I can't think of an example where having a ForEach would be useful syntacticly.
Cameron MacFarland
But what happens if you have a delegate already? :)
leppie
leppie: You call the delegate in the foreach :)
Coincoin
If DoSomething was a local/static method, then it would look much cleaner using the ForEach method: list.ForEach(DoSomething);
Nathan Baulch
mancaus
But, Mancaus, Enumerable already has extension method with side effect . Such as Count and Reverse.
Morgan Cheng
sometimes it's clearer with the extension method, don't try to pretend using statement lambda synthax: list.ForEach( item => item.DoSomething());
Olmo
'foreach' may seem clearer if you have a C background, but internal iteration more clearly states your intent. That means you could do things like 'sequence.AsParallel().ForEach(...)'.
Jay Bazuzi
@Morgan, What side effects does Count and Reverse have? As far as I know, they do nothing to the original enumeration. Same with OrderBy and its relatives. The original whatever-it-was is left untouched.
Svish
A: 

If you have F# (which will be in the next version of .Net), you can use

Seq.iter doSomething myIEnumerable

TraumaPony
+1  A: 

Is it me or is the List<T>.Foreach pretty much been made obsolete by Linq. Originally there was

foreach(X x in Y)

where Y simply had to be IEnumerable (Pre 2.0), and implement a GetEnumerator(). If you look at the MSIL generated you can see that it is exactly the same as

IEnumerator&lt;int&ft; enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
    int i = enumerator.Current;

    Console.WriteLine(i);
}

(See http://alski.net/post/0a-for-foreach-forFirst-forLast0a-0a-.aspx for the MSIL)

Then in DotNet2.0 Generics came along and the List.Foreach has always felt to me to be an implementation of the Vistor pattern, (see Design Patterns by Gamma, Helm, Johnson, Vlissides).

Now of course in 3.5 we can instead use a Lambda to the same effect, for an example try http://dotnet-developments.blogs.techtarget.com/2008/09/02/iterators-lambda-and-linq-oh-my/

I believe the generated code for "foreach" should have a try-finally block. Because IEnumerator of T inherits from interface IDisposable. So, in the generated finally block, the IEnumerator of T instance should Disposed.
Morgan Cheng
+2  A: 

So there has been a lot of comments about the fact that a ForEach extension method isn't appropriate because it doesn't return a value like the LINQ extension methods. While this is a factual statement, it isn't entirely true.

The LINQ extension methods do all return a value so they can be chained together:

collection.Where(i => i.Name = "hello").Select(i => i.FullName);

However, just because LINQ is implemented using extension methods does not mean that extension methods must be used in the same way and return a value. Writing an extension method to expose common functionality that does not return a value is a perfectly valid use.

The specific arguement about ForEach is that, based on the constraints on extension methods (namely that an extension method will never override an inherited method with the same signature), there may be a situation where the custom extension method is available on all classes that impelement IEnumerable<T> except List<T>. This can cause confusion when the methods start to behave differently depending on whether or not the extension method or the inherit method is being called.

Scott Dorman
+1  A: 

You can use select when you want to return something. If you don't, you can use ToList first, because you probably don't want to modify anything in the collection.

Paco
+5  A: 

While I agree that it's better to use the built-in foreach construct in most cases, I find the use of this variation on the ForEach<> extension to be a little nicer than having to manage the index in a regular foreach myself:

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

    var index = 0;

    foreach (var elem in list)
        action(index++, elem);

    return index;
}
Example
var people = new[] { "Moe", "Curly", "Larry" };
people.ForEach((i, p) => Console.WriteLine("Person #{0} is {1}", i, p));

Would give you:

Person #0 is Moe
Person #1 is Curly
Person #2 is Larry
Chris Zwiryk
This is a great extension method. I will be using it in the future.
Brian Genisio
Great extension, but could you add some documentation? What is the intended use of the returned value? Why is index var rather than specifically an int? Sample usage?
Mark T
Mark: The return value is the number of elements in the list. Index *is* specifically typed as an int, thanks to implicit typing.
Chris Zwiryk
@Chris, based on your code above, the return value is the zero-based index of the last value in the list, not the number of elements in the list.
Eric Smith
@Eric, thanks for catching that.
Chris Zwiryk
@Chris, no it isn't: index is incremented after the value has been taken (postfix increment), so after the first element has been processed, index will be 1 and so on. So the return value really is the element count.
MartinStettner
@MartinStettner, no what? This method is supposed to return the element count.
Chris Zwiryk
A: 

To all those who opt for 'foreach' statement. What about method chaining, like that:

        IEnumerable<string> people;
        people.GroupBy(p => p[0])
            .ForEach(g => Console.WriteLine("There are " + g.Count() + " people with names starting in " + g.Key))
            .Where(g => g.Key == 'S')
            .First().ForEach(p => Console.WriteLine(">>> " + p));

Of course this example is pretty stupid, I just want to open your imperative-oriented brains... ;)

ForEach will not return anything, so it can only go on the end of a method chain.
Cameron MacFarland
Actually, for some extension method defined in class Enumerable, e.g. Count(), it also can only be at the end of method chain.
Morgan Cheng
Ouch! I'm in favor of anything that discourages people from writing nightmare chained code like that. I can't even parse what you're trying to accomplish with it.
Jason Kester
This is a jQuery pattern that makes complete sense to me. Though, it's commonplace to indent the chained calls where the data set has been modified (such as `GroupBy`, `Where` and `First`).
spoulson
+9  A: 

The discussion here gives the answer.

Basically the decision was made to keep the extension methods functionally "pure". A ForEach would encourage side-effects when using the Enumerable extension methods, which was not the intent.

mancaus
That link is out of date, new one: http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/2dddb3b1-5ea3-41a6-880a-f994acf0a68b/
Richard
+1  A: 

One workaround is to write .ToList().ForEach(x => ...).

pros

Easy to understand - reader only needs to know what ships with C#, not any additional extension methods.

Syntactic noise is very mild (only adds a little extranious code).

Doesn't usually cost extra memory, since a native .ForEach() would have to realize the whole collection, anyway.

cons

Order of operations isn't ideal. I'd rather realize one element, then act on it, then repeat. This code realizes all elements first, then acts on them each in sequence.

If realizing the list throws an exception, you never get to act on a single element.

If the enumeration is infinite (like the natural numbers), you're out of luck.

Jay Bazuzi
+14  A: 

You could write this extension method:

// Possibly call this "Do"
IEnumerable<T> Apply<T> (this IEnumerable<T> source, Action<T> action)
{
 foreach (var e in source)
 {
  action(e);
  yield return e;
 }
}

Pros

Allows chaining:

MySequence
 .Apply(...)
 .Apply(...)
 .Apply(...);

Cons

It won't actually do anything until you do something to force iteration. For that reason, it shouldn't be called .ForEach(). You could write .ToList() at the end, or you could write this extension method, too:

// possibly call this "Realize"
IEnumerable<T> Done<T> (this IEnumerable<T> source)
{
 foreach (var e in source)
 {
  // do nothing
  ;
 }
}

This may be too significant a departure from the shipping C# libraries; readers who are not familiar with your extension methods won't know what to make of your code.

Jay Bazuzi
A: 

@Coincoin

The real power of the foreach extension method involves reusability of the Action<> without adding unnecessary methods to your code. Say that you have 10 lists and you want to perform the same logic on them, and a corresponding function doesn't fit into your class and is not reused. Instead of having ten for loops, or a generic function that is obviously a helper that doesn't belong, you can keep all of your logic in one place (the Action<>. So, dozens of lines get replaced with

Action<blah,blah> f = { foo };

List1.ForEach(p => f(p))
List2.ForEach(p => f(p))

etc...

The logic is in one place and you haven't polluted your class.

foreach (var p in List1.Concat(List2).Concat(List3)){ ... do stuff... }
Cameron MacFarland
If it's as simple as `f(p)`, then leave out the `{ }` for shorthand: `for (var p in List1.Concat(List2).Concat(List2)) f(p);`.
spoulson
+1  A: 

No one has yet pointed out that ForEach<T> results in compile time type checking where the foreach keyword is runtime checked.

Having done some refactoring where both methods were used in the code, I favor .ForEach, as I had to hunt down test failures / runtime failures to find the foreach problems.

Squirrel
+1  A: 

I wrote a blog post about it: http://blogs.msdn.com/kirillosenkov/archive/2009/01/31/foreach.aspx

You can vote here if you'd like to see this method in .NET 4.0: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=279093

Kirill Osenkov
A: 

In 3.5, all the extension methods added to IEnumerable are there for LINQ support (notice that they are defined in the System.Linq.Enumerable class). In this post, I explain why foreach doesn't belong in LINQ: http://stackoverflow.com/questions/317874/existing-linq-extension-method-similar-to-parallel-for/318493#318493

Neil Whitaker