views:

19659

answers:

10

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:

IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());

What is the real syntax?

+59  A: 

There is no ForEach extension for IEnumerable; only for List. So you could do

items.ToList().ForEach(i => i.DoStuff());

Alternatively, write your own ForEach extension:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}
Fredrik Kalseth
Honestly I think the normal foreach construct is more readable than the extension method in most cases.
Matt Hamilton
I used to have a method like this in my code, but really ToList().ForEach() solves the problem and I feel that Jon's answer, below, is more correct.
cfeduke
Be careful with ToList(), because ToList() creates a copy of the sequence, which could cause performance and memory issues.
decasteljau
There are few reasons why ".Foreach()" will be better.1. Multi-threading, possible by PLINQ.2. Exceptions, you may want to collect all exception in the loop and throw it at once; and they are noise codes.
Dennis Cheung
I wonder if there is a convenient way to make a ForEach implementation like this that can have deferred execution? Might be handy although I think it is probably worse as far as the concern about side effects.
jpierson
PLINQ uses ForAll not ForEach, which is why you wouldn't use ForEach.
sixlettervariables
A: 

There is none.

You have to use the 'foreach' keyword, or do it C# 1.0 style.

TraumaPony
What's C# 1 style? I am sure there was a foreach in the language at the time...
Martinho Fernandes
+4  A: 

If you can use IQueryable<T> instead of IEnumerable<T>, then the Select method should do what you want.

IQueryable<Item> items = GetItems();
IQueryable<Item> modifiedItems = items.Select(i => i.DoStuff());

LINQ's select method doesn't really have anything in common with the SQL SELECT keyword; what it does is apply a function to each element in a set, and return a set containing the results of those functions.

Dylan Beattie
This assummes that i.DoStuff() returns an Item (either the modified i or a new copy). And why can't it be done with IEnumerable<T>?
Lucas
Why wouldn't `DoStuff()` return an item? If you have the code for `Item`, you can make return whatever you want. If you don't, you can create an extension method.
toast
Even though it is called select, it doesn't actually have to return anything!
SkippyFire
Just a quick (very belated) note on this answer: The Select method call won't be triggered until you force modifiedItems to enumerate, either by for-eaching through it or calling ToList(), ToArray() etc.
Martin Harris
+48  A: 

Fredrik has provided the fix, but it may be worth considering why this isn't in the framework to start with. I believe the idea is that the LINQ query operators should be side-effect-free, fitting in with a reasonably functional way of looking at the world. Clearly ForEach is exactly the opposite - a purely side-effect-based construct.

That's not to say this is a bad thing to do - just thinking about the philosophical reasons behind the decision.

Jon Skeet
For reference, this question poses the same question, and gets input from "the powers that be": http://stackoverflow.com/questions/858978/lambda-expression-using-foreach-clause
Benjol
Exactly what Eric Lippert states in http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
Alex Angas
And yet, F# has Seq.iter
Stephen Swensen
+1 Skeet fact - every time that Jon Skeet speaks, a new programming language is created.
Repo Man
However, there's one very useful thing that LINQ functions typically provide that foreach () doesn't - the anonymous function taken by Linq functions can also take an index as a parameter, whereas with foreach you must rebuild the classic for (int i..) construct. And functional languages have to allow iteration that has side effects - otherwise you could never do one iota of work with them :) I'd like to point out that the typical functional method would be to return the original enumerable unchanged.
Walt W
@Walt: If a typical functional method returned the original enumerable and *didn't* have side-effects (which *typical* functional methods don't) then it would have no effect at all. Perhaps you could clarify your comment?
Jon Skeet
@Jon Skeet: Essentially, with any language, you're always going to have to output or otherwise pass along some material to "get work done" (output to file, progress inform, whatever). That's where foreach constructs have a place in a functional environment - performing those sorts of actions. So saying that it doesn't have side effects is the same as saying you don't need a foreach.
Walt W
@Jon Skeet - As for clarifying my post a bit, perhaps I should rephrase the last sentence: "I'd like to point out that the typical functional _approach with a foreach_ would be to return the original enumerable unchanged"
Walt W
@Walt: I'm still not sure I agree, partly because a typical truly functional approach wouldn't *use* foreach like this... it would use a functional approach more like LINQ, creating a new sequence.
Jon Skeet
@Jon: Well, that I agree with; hence the "saying it doesn't have side effects is the same as saying you don't need a foreach". But LINQ isn't academically functional, is it? I'd consider it a practical functional construct within C#. Practicality (unfortunately?) requires side effects... And so I don't believe it would be philosophically inappropriate to add this construct to LINQ just because of side effects. It might be more appropriate, however, to provide a method for fetching the index in the body of a foreach. But it would be nice to have in both places.
Walt W
@Walt: Practicality doesn't need side effects *everywhere* though. Usually I'd use LINQ for the side-effect-free part, and then a `foreach` loop for the side-effecting part of the code. If you want the index in `foreach`, you can either use `foreach (var pair in sequence.Select((value, index) => new { value, index }))` or use my SmartEnumerable class from MiscUtil which is much the same: http://www.yoda.arachsys.com/csharp/miscutil/usage/smartenumerable.html
Jon Skeet
@Jon: Adding a ForEach to LINQ doesn't encourage using it everywhere. You are right that they don't need to be everywhere though. And I know there's equivalent user code; personally I'd prefer just using an for() loop than constructing a new list of completely new objects just to access the index. Language / official library support would be nice. But yes, user code is a currently viable option.
Walt W
A: 

I respectually disagree with the notion that link extension methods should be side-effect free (not only because they aren't, any delegate can perform side effects).

Consider the following:

   public class Element {}

   public Enum ProcessType
   {
      This = 0, That = 1, SomethingElse = 2
   }

   public class Class1
   {
      private Dictionary<ProcessType, Action<Element>> actions = 
         new Dictionary<ProcessType,Action<Element>>();

      public Class1()
      {
         actions.Add( ProcessType.This, DoThis );
         actions.Add( ProcessType.That, DoThat );
         actions.Add( ProcessType.SomethingElse, DoSomethingElse );
      }

      // Element actions:

      // This example defines 3 distict actions
      // that can be applied to individual elements,
      // But for the sake of the argument, make
      // no assumption about how many distict
      // actions there may, and that there could
      // possibly be many more.

      public void DoThis( Element element )
      {
         // Do something to element
      }

      public void DoThat( Element element )
      {
         // Do something to element
      }

      public void DoSomethingElse( Element element )
      {
         // Do something to element
      }

      public void Apply( ProcessType processType, IEnumerable<Element> elements )
      {
         Action<Element> action = null;
         if( ! actions.TryGetValue( processType, out action ) )
            throw new ArgumentException("processType");
         foreach( element in elements ) 
            action(element);
      }
   }

What the example shows is really just a kind of late-binding that allows one invoke one of many possible actions having side-effects on a sequence of elements, without having to write a big switch construct to decode the value that defines the action and translate it into its corresponding method.

What's the point here?
Stefan Steinegger
There's a difference between whether an extension method CAN have side-effectsand whether it SHOULD have. You're only pointing out that it can have, while there may be very good reasons to propose that they should not have side effects. In functional programming, all functions are side-effect free, and when using functional programming constructs you may want to assume that they are.
Dave Van den Eynde
+2  A: 

I took Fredrik's method and modified the return type.

This way, the method supports deferred execution like other LINQ methods.

EDIT: If this wasn't clear, any usage of this method must end with ToList() or any other way to force the method to work on the complete enumerable. Otherwise, the action would not be performed!

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

And here's the test to help see it:

[Test]
public void TestDefferedExecutionOfIEnumerableForEach()
{
    IEnumerable<char> enumerable = new[] {'a', 'b', 'c'};

    var sb = new StringBuilder();

    enumerable
        .ForEach(c => sb.Append("1"))
        .ForEach(c => sb.Append("2"))
        .ToList();

    Assert.That(sb.ToString(), Is.EqualTo("121212"));
}

If you remove the ToList() in the end, you will see the test failing since the StringBuilder contains an empty string. This is because no method forced the ForEach to enumerate.

Dor Rotman
A: 

yet another ForEach Example

public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
    var workingAddresses = new List<AddressEntry>();

    addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));

    return workingAddresses;
}
neil martin
A: 

The purpose of ForEach is to cause side effects. IEnumerable is for lazy enumeration of a set.

This conceptual difference is quite visible when you consider it.

SomeEnumerable.ForEach(item=>DataStore.Synchronize(item));

This wont execute until you do a "count" or a "ToList()" or something on it. It clearly is not what is expressed.

You should use the IEnumerable extensions for setting up chains of iteration, definining content by their respective sources and conditions. Expression Trees are powerful and efficient, but you should learn to appreciate their nature. And not just for programming around them to save a few characters overriding lazy evaluation.

Tormod
A: 

If you're doing this e.g. because you need the index in your iteration, you could always use a Where construct:

linqObject.Where((obj, index) => {
  DoWork(obj, index);
  return true;
}).ToArray(); //MUST CALL ToArray() or ToList() or something to execute the lazy query, or the loop won't actually execute

This has the added benefit that the original array is returned "unchanged" (the objects referenced by the list are the same, though they may not have the same data), which is often desireable in functional / chain programming methodologies like LINQ.

Walt W
A: 

You could use the FirstOrDefault() extension, which is available for IEnumerable. By returing false from the predicate, it will be run for each element but will not care that it doesn't actually find a match. This will avoid the ToList() overhead.

        IEnumerable<Item> items = GetItems();
        items.FirstOrDefault(i => { i.DoStuff(); return false; });
Rhames