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.
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:
The common consensus is that LINQ is for querying and selection... while you use traditional iterative methods for looping and iteration.
I hate to say this but you would use a traditional foreach loop because you want your linq queries to execute, and you iterate over the resulting IEnumerable. It helps with code readability, and I will admit LINQ is addictive. You want to do everything using Lambdas and deferred execution, but looping should be left to your traditional C# looping methods. This will definitely help with side-effects.