Назначение значений внутри LINQ Select?

У меня есть следующий запрос:

drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList();

драйверы - это список, в который входят разные идентификаторы и обновленные значения, поэтому я изменяю значения в Select, но это правильный способ сделать это. Я уже знаю, что я не переназначаю драйверы драйверам, потому что Resharper жалуется на это, поэтому я думаю, было бы лучше, если бы это было:

drivers = drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList();

но это все еще так, как кто-то должен назначать новые значения для каждого элемента в списке драйверов?

Ответ 1

Хотя это выглядит невинно, особенно в сочетании с вызовом ToList который немедленно ToList код, я определенно избегаю модификации чего-либо как части запроса: трюк настолько необычен, что он будет затягивать читателей вашей программы, даже опытных, особенно если они никогда не видели этого раньше.

Нет ничего плохого в петлях foreach - факт, что вы можете сделать это с LINQ, не означает, что вы должны это делать.

Ответ 2

НИКОГДА НЕ ДЕЛАЙТЕ ЭТО. Запрос должен быть запросом; это должно быть неразрушающим образом задавать вопросы источника данных. Если вы хотите вызвать побочный эффект, используйте цикл foreach; что это для. Используйте правильный инструмент для работы.

Ответ 3

Хорошо, я сам отвечу.

Xaisoft, запросы Linq, будь то выражение lambda или выражение запроса, не должны использоваться для изменения списка. Следовательно, ваш Select

drivers = drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList();

плохой стиль. Это смущает/нечитабельно, а не стандартно, а также против философии Linq. Еще один плохой стиль достижения конечного результата:

drivers.Any(d => { d.id = 0; d.updated = DateTime.Now; return false; });

Но это не ForEach что ForEach on List<T> не подходит. Он находит использование в таких случаях, как ваш, но не смешивает мутацию с запросом Linq, вот и все. Я предпочитаю писать что-то вроде:

drivers.ForEach(d => d.updated = DateTime.Now);

Его элегантный и понятный. Поскольку это не касается Linq, это тоже не смущает. Мне не нравится этот синтаксис для нескольких операторов (как в вашем случае) внутри лямбда. Это немного менее читаемо и сложнее отлаживать, когда все становится сложным. В вашем случае я предпочитаю прямой цикл foreach.

foreach (var d in drivers)
{ 
    d.id = 0; 
    d.updated = DateTime.Now; 
}

Лично мне нравится ForEach на IEnumerable<T> как завершающий вызов выражения Linq (т. Linq Если назначение не предназначено для запроса, а является исполнением).