Отправка объектов в LINQ упорядочивает к методу, который возвращается пусто

Часто, в то время как я имею дело с последовательностями LINQ, я хочу отправить каждый объект в метод, возвращаясь пусто, избегая цикла 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, и я понимаю, что Избранный метод возвратит последовательность булевских переменных - я просто проигнорирую ту последовательность. Однако это кажется небольшим noobish и jank. Там какой-либо изящный путь состоит в том, чтобы сделать это? Или я просто неправильно употребляю LINQ?

Спасибо.

13
задан Ray Vega 13 July 2011 в 00:45
поделиться

2 ответа

Прежде всего, ваш текущий код не будет работать.
Select и большинство других методов LINQ используют отложенное выполнение, что означает, что они фактически ничего не делают, пока вы не перечислите результаты.

В общем, вы никогда не должны использовать лямбду с побочными эффектами в LINQ-запросе.

Чтобы ответить на ваш вопрос, вы должны использовать цикл foreach.

Вы ищете метод расширения ForEach; Эрик Липперт объясняет, почему Microsoft его не написала.

Если вы действительно хотите, вы можете написать его сами:

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;
}
15
ответ дан 1 December 2019 в 22:56
поделиться

По общему мнению, LINQ предназначен для запросов и выбора .. .. пока вы используете традиционные итерационные методы для циклов и итераций.

Ненавижу это говорить, но вы бы использовали традиционный цикл foreach, потому что хотите, чтобы ваши запросы linq выполнялись, и вы перебираете получившийся IEnumerable. Это помогает с удобочитаемостью кода, и я признаю, что LINQ вызывает привыкание. Вы хотите делать все, используя Lambdas и отложенное выполнение, но выполнение цикла следует оставить на усмотрение традиционных методов цикла C #. Это определенно поможет с побочными эффектами.

5
ответ дан 1 December 2019 в 22:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: