Sending items in a LINQ sequence to a method that returns void

a developer picture a developer · Mar 12, 2010 · Viewed 7.2k times · Source

Often while I'm dealing with LINQ sequences, I want to send each item to a method returning void, avoiding a foreach loop. However, I haven't found an elegant way to do this. Today, I wrote the following code:

    private StreamWriter _sw;
    private void streamToFile(List<ErrorEntry> errors)
    {
        if (_sw == null)
        {
            _sw = new StreamWriter(Path.Combine
                                    (Path.GetDirectoryName(_targetDatabasePath), "errors.txt"));
        }

        Func<ErrorEntry, bool> writeSelector = 
            (e) => { _sw.WriteLine(getTabDelimititedLine(e)); return true; };

        errors.Select(writeSelector);

        _sw.Flush();
    }

As you can see, I write a lambda function that just returns true, and I realize that the Select method will return a sequence of booleans- I'll just ignore that sequence. However, this seems a little bit noobish and jank. Is there any elegant way to do this? Or am I just misapplying LINQ?

Thanks.

Answer

SLaks picture SLaks · Mar 12, 2010

First of all, your current code will not work.
Select, and most other LINQ methods, use deferred execution, meaning that they don't actually do anything until you enumerate the results.

In general, you should never use a lambda with side effects in a LINQ query.

To answer your question, you should use a foreach loop.

You're looking for a ForEach extension method; Eric Lippert explains why Microsoft didn't write one.

If you really want to, you can write one yourself:

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

//Return false to stop the loop
public static void ForEach<T>(this IEnumerable<T> sequence, Func<T, bool> action) {
    if (sequence == null) throw new ArgumentNullException("sequence");
    if (action == null) throw new ArgumentNullException("action");

    foreach(T item in sequence) 
        if (!action(item))
            return;
}