2013-05-16 16 views
14

我有以下查询:在LINQ Select中分配值?

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

驱动程序是不同的ID和更新的值是在一个列表,所以我改变选择的值,但这样做的正确方法。我已经知道,我不是重新分配驱动程序驱动程序,因为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查询,不管是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; }); 

但是,这并不是说ForEachList<T>是不合适的。它在像你这样的案例中找到用途,但不要将突变与Linq查询混合使用,即所有。我更喜欢写这样的:

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

它的优雅和可以理解。由于它不涉及Linq,它也不会造成混淆。我不喜欢lambda内多个语句的语法(如你的情况)。当情况变得复杂时,它的可读性和可读性都会降低一些。在你的情况下,我更喜欢直接foreach循环。

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

个人而言,我喜欢ForEachIEnumerable<T>as a terminating call to Linq expression(即,如果转让并不意味着是一个查询,但执行)。

+0

感谢您的好解释。 – Xaisoft

+0

@Xaisoft事实上,我讨厌'列表上的'ForEach'是他们默认显示的事实。我不认为它适合作为框架级别的结构。我更喜欢用户自行决定的更高级别的构造,作为扩展或更新。如果量身定做的东西可以帮助最终用户,那就去做吧。这里有很多令人讨厌的东西,如果它的制作合适与否,可以由个人决定。 [这是'Type'实现的另一个'switch-case',](http://stackoverflow.com/a/1426626/661933)以及它的真棒。拥抱它或转身离去。不要喋喋不休.. – nawfal

+0

谁在嘲笑它,它是什么? – Xaisoft