在LINQ Select中分配值?

Xai*_*oft 16 c# linq

我有以下查询:

drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList();
Run Code Online (Sandbox Code Playgroud)

drivers是一个List,它带有不同的id和更新的值,因此我在更改Select中的值,但这是正确的方法.我已经知道我没有给司机重新分配司机,因为Resharper抱怨它,所以我想如果是这样会更好:

drivers = drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList();
Run Code Online (Sandbox Code Playgroud)

但这仍然是某人应该为驱动程序列表中的每个元素分配新值的方式吗?

das*_*ght 34

虽然这看起来很无辜,特别是与一个ToList立即执行代码的调用相结合,但我肯定会远离修改任何东西作为查询的一部分:这个技巧是如此不寻常以至于它会让你的程序的读者绊倒,即使是经验丰富的程序,特别是如果他们以前从未见过这个.

foreach循环没有问题- 你可以用LINQ做这件事并不意味着你应该这样做.

  • +1 LINQ不应该用于对象变异. (8认同)
  • 但是,如果我确实使用了ForEach,那么就可读性而言,那会是更好的选择吗? (2认同)

Eri*_*ert 30

永远不要这样做.查询应该是查询 ; 它应该是非破坏性地询问数据源的问题.如果你想引起副作用,那就用一个foreach循环; 这就是它的用途.使用正确的工具完成工作.

  • 谢谢埃里克.知道正确方法的唯一方法就是先知道你做错了:) (5认同)

naw*_*fal 7

好的,我会自己回答.

Xaisoft,Linq查询,无论是lambda表达式还是查询表达式,都不应该用于变异列表.因此你的Select

drivers = drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList();
Run Code Online (Sandbox Code Playgroud)

是不好的风格.它混淆/不可读,不标准,反对Linq哲学.实现最终结果的另一种糟糕方式是:

drivers.Any(d => { d.id = 0; d.updated = DateTime.Now; return false; });
Run Code Online (Sandbox Code Playgroud)

但是,这并不是说ForEachList<T>是不合适的.它可以在像你这样的情况下找到用途,但不要将变异与Linq查询混合在一起,就是这样.我更喜欢这样写:

drivers.ForEach(d => d.updated = DateTime.Now);
Run Code Online (Sandbox Code Playgroud)

它优雅而易懂.既然它没有处理Linq,它也不会混淆.我不喜欢lambda中的多个语句(如你的情况)的语法.当事情变得复杂时,它的可读性会降低一点,也难以调试.在你的情况下,我更喜欢直接foreach循环.

foreach (var d in drivers)
{ 
    d.id = 0; 
    d.updated = DateTime.Now; 
}
Run Code Online (Sandbox Code Playgroud)

我个人喜欢ForEachIEnumerable<T> 作为终止呼叫以Linq表达(即,如果该分配并不意味着是一个查询,但执行).