2013-05-16 2 views
14

У меня есть следующий запрос:Назначение значений внутри 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(); 

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

+0

Возможный дубликат [Linq побочные эффекты] (http: // stackoverflow.com/questions/5632222/linq-side-effects) – nawfal

ответ

33

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

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

+0

Я бы использовал 'ForEach' для оператора с одной строкой, а не для чего-то, что требует фигурных скобок (несколько операторов). 'foreach' действительно лучше здесь. – nawfal

+0

Вы правы, это сотрясало меня :) Я согласен с вашим вторым заявлением. – Xaisoft

+8

+1 LINQ не следует использовать для мутации объекта. – recursive

28

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

+4

Спасибо Эрик. Единственный способ узнать правильный путь - знать, что вы делаете это неправильно, в первую очередь :) – Xaisoft

7

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

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

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

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

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

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

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

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

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

Лично мне нравится ForEach на IEnumerable<T>as a terminating call to Linq expression (то есть, если назначение не означает быть запрос, но казнь).

+0

Спасибо за хорошее объяснение. – Xaisoft

+0

@ Xaisoft На самом деле то, что я ненавижу о 'ForEach' в' List ', - это тот факт, что они появляются по умолчанию. Я не думаю, что он подходит как конструкция уровня структуры. Я предпочитаю такие конструкции более высокого уровня, поступающие по усмотрению пользователя, как расширение или около того. Если специализированные изделия помогают конечному пользователю, хорошо подойдите к нему. Есть много geeky собирается там и его до отдельных лиц, чтобы выбрать, если его производство подходит или нет. [Вот еще один «switch-case», реализованный для 'Type',] (http://stackoverflow.com/a/1426626/661933), и это потрясающе. Обнимите его или отверните. Не сука об этом .. – nawfal

+0

Кто это сует и что это? – Xaisoft

Смежные вопросы