Часто, в то время как я имею дело с последовательностями 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?
Спасибо.
Прежде всего, ваш текущий код не будет работать.
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;
}
По общему мнению, LINQ предназначен для запросов и выбора .. .. пока вы используете традиционные итерационные методы для циклов и итераций.
Ненавижу это говорить, но вы бы использовали традиционный цикл foreach, потому что хотите, чтобы ваши запросы linq выполнялись, и вы перебираете получившийся IEnumerable. Это помогает с удобочитаемостью кода, и я признаю, что LINQ вызывает привыкание. Вы хотите делать все, используя Lambdas и отложенное выполнение, но выполнение цикла следует оставить на усмотрение традиционных методов цикла C #. Это определенно поможет с побочными эффектами.