15

通常在处理 LINQ 序列时,我想将每个项目发送到返回 void 的方法,从而避免 foreach 循环。但是,我还没有找到一种优雅的方法来做到这一点。今天,我写了以下代码:

    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();
    }

如您所见,我编写了一个仅返回 true 的 lambda 函数,并且我意识到 Select 方法将返回一个布尔序列——我将忽略该序列。但是,这似乎有点笨拙和卡顿。有什么优雅的方法可以做到这一点吗?还是我只是误用了 LINQ?

谢谢。

4

2 回答 2

19

首先,您当前的代码将不起作用。
Select和大多数其他 LINQ 方法都使用延迟执行,这意味着它们实际上在您枚举结果之前不会执行任何操作。

通常,您永远不应该在 LINQ 查询中使用具有副作用的 lambda。

要回答您的问题,您应该使用foreach循环。

您正在寻找ForEach扩展方法;Eric Lippert 解释了为什么微软没有编写一个.

如果你真的想,你可以自己写一个:

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;
}
于 2010-03-12T02:06:20.813 回答
6

普遍的共识是 LINQ 用于查询和选择......而您使用传统的迭代方法进行循环和迭代。

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.

于 2010-03-12T14:11:03.043 回答