46

I started dabbling in Windows 8 metro recently, and found that one of my old buddies seems to have gone missing.

I tend to use the .ForEach() method more than I use the traditional foreach() construct, and I realized pretty quickly that this method isn't available. For example, this code will not compile under a metro app:

var list = new List<string>();

list.ForEach(System.Diagnostics.Debug.WriteLine);

I've searched to see if I could find any discussion of this, but wasn't able to. Am I just being obtuse, or is it actually gone?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Robaticus
  • 22,857
  • 5
  • 54
  • 63

3 Answers3

43

It's indeed gone:

List<T>.ForEach has been removed in Metro style apps. While the method seems simple it has a number of potential problems when the list gets mutated by the method passed to ForEach. Instead it is recommended that you simply use a foreach loop.


Wes Haggard | .NET Framework Team (BCL) | http://blogs.msdn.com/b/bclteam/

Very strangely, however, it makes an appearance in the documentation, in which nowhere does it state that this method isn't supported in .NET for Windows Store apps (formerly .NET for Metro-style apps). Perhaps this is just an oversight on part of the documentation team.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 1
    @Robaticus: You can just add your own extension method to replace it. Probably would be best to call `.ToList()` first, then iterate that. Nothing like iterating a source while trying to mutate it to ruin your day. –  Apr 24 '12 at 14:59
  • 1
    @Will - I agree that I could do it. It's probably a good habit to get out of, though, particularly when showing new LINQ programmers how to do things. – Robaticus Apr 24 '12 at 15:37
19

To get a sense for why it might no longer be included, read this post by someone who works on the C# team at Microsoft: http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

Basically, it's philosophy. The "LINQ" features are highly inspired by the functional programming paradigm, and the ForEach extension flies in the face of that... it encourages poor functional style.

Also see this answer for more details:

https://stackoverflow.com/a/529197/3043

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
16

An alternative is to define it yourself of course:

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
        yield return item;
    }
}

Credit: LINQ equivalent of foreach for IEnumerable<T>

(Note: not a duplicate)

Community
  • 1
  • 1
yamen
  • 15,390
  • 3
  • 42
  • 52
  • 2
    Although this is definitely acceptable practice, just be careful that it doesn't modify any requirements of previous IEnumerable calls (such as a Where or OrderBy). Also, if you want to continue chaining the IEnumerable calls, you can change the return type to `IEnumerable` and `yield return item` after performing the action on the item. However, this will still mutate the elements, so be aware that these "side effects" might alter the enumeration. – SPFiredrake Apr 25 '12 at 18:07
  • Yes, ForEach is certainly dangerous. I've updated the answer to return `IEnumerable` in order to allow continued chaining, but this is probably likely to make things more dangerous. – yamen Apr 25 '12 at 20:34