在LINQ的Select中赋值?

21

我有以下查询:

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

drivers是一个列表,其中包含不同的id和更新的值,因此我通过更改Select中的值来修改它们,但这样做是否正确我不确定。我已经知道不能将drivers重新分配给drivers,因为Resharper会报错,所以我想最好还是这样:

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

但是,这仍然是将新值分配给驱动程序列表中每个元素的方式吗?


可能是Linq副作用的重复问题。 - nawfal
另一个可能的重复问题 https://dev59.com/d2sz5IYBdhLWcg3wFT4f#62326244 - Marisol Gutiérrez
3个回答

38
尽管这看起来很无害,特别是与立即执行代码的 ToList 调用结合使用时,但我绝对会远离将任何修改作为查询的一部分:这种技巧非常不寻常,会让程序的读者——即使是经验丰富的读者,尤其是如果他们以前从未见过这种情况——感到困惑。 foreach 循环并没有什么问题 - 事实上,你可以使用 LINQ 做到这一点,并不意味着你应该这样做。

1
我会在单行语句中使用 ForEach,而不是需要花括号(多个语句)的情况。在这里使用 foreach 确实更好。 - nawfal
你说得对,这让我有些困惑 :) 我也同意你的第二个陈述。 - Xaisoft
2
但如果我使用ForEach,就从可读性的角度来看,那是否是更好的选择? - Xaisoft
1
@Xaisoft ForEach 可能效果更好,但它不是 LINQ 的一部分:它是在 List<T> 上定义的,而不是在 IEnumerable<T> 上定义的,所以我几乎可以确定它是建立在修改的想法上的(当然,只要列表本身保持完整)。使用 foreach 循环 vs. List<T>.ForEach 是个人偏好的问题。 - Sergey Kalinichenko
@nawfal,抱歉打错字了。关于List是否应该存在ForEach方法存在争议。(下面的Lippert先生之前已经对此发表了他的看法):http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx - Kirk Woll
显示剩余3条评论

33

千万不要这样做。 查询应该是一个查询;它应该是对数据源进行无损问询。如果你想引起副作用,那么请使用foreach循环;这才是它的用途。使用正确的工具完成任务。


5
谢谢,Eric。唯一知道正确方式的方法是首先意识到自己做错了 :) - Xaisoft

9

好的,我会自己回答。

Xaisoft,无论是lambda表达式还是查询表达式,Linq查询都不应该用于更改列表。因此,您的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; });

但这并不意味着在List<T>上使用ForEach是不恰当的。它在像你这样的情况下有用途,但不要将更改与Linq查询混合使用,就是这样。我更喜欢编写像这样的代码:

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

这段代码优雅易懂,因为它没有涉及到 Linq ,所以不会令人困惑。我不喜欢在 lambda 表达式中编写多个语句的语法(就像你的情况一样)。当事情变得复杂时,这种语法稍微难读一些,也更难调试。在你的情况下,我更喜欢使用普通的 foreach 循环。

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

就个人而言,我喜欢在 IEnumerable<T> 上使用 ForEach 作为 Linq 表达式的终止调用(即,如果赋值不是查询而是执行)。


@Xaisoft 实际上,我讨厌 List<T> 上的 ForEach 默认出现的事实。我认为它不适合作为框架级别的构造。我更喜欢这样的高级构造以用户的自由裁量方式出现,例如作为扩展等。如果定制的东西有助于最终用户,那就去做吧。里面有很多极客的东西,取决于个人选择是否适合生产。这里是另一个针对 Type 实现的 switch-case,太棒了。拥抱它或者离开。不要抱怨。 - nawfal
@Xaisoft,无论是谁做的,都没有特指任何人 :) - nawfal
其中一个问题是,当你被给予太多选项时,你可能不知道该怎么做。正如Eric Lippert所指出的那样,这部分取决于经验和知道适合工作的正确工具。 - Xaisoft
1
@Xaisoft 我同意,你的问题也很相关。 - nawfal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接