【问题标题】:Assigning values inside a LINQ Select?在 LINQ Select 中分配值?
【发布时间】:2013-05-11 18:23:02
【问题描述】:

我有以下疑问:

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

drivers 是一个包含不同 id 和更新值的列表,因此我正在更改 Select 中的值,但这是正确的方法。我已经知道我不会将驱动程序重新分配给驱动程序,因为 Resharper 会抱怨它,所以我想如果是这样会更好:

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

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

【问题讨论】:

标签: c# linq


【解决方案1】:

好的,我自己来回答。

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; });

但这并不是说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; 
}

我个人喜欢ForEach on IEnumerable<T> as a terminating call to Linq expression(即,如果分配不是要查询而是执行)。

【讨论】:

  • @Xaisoft 实际上,我讨厌List<T> 上的ForEach 是它们默认出现的事实。我认为它不适合作为框架级别的构造。我更喜欢这种由用户自行决定的更高级别的构造,例如扩展名左右。如果量身定制的东西可以帮助最终用户,那就去吧。那里有很多令人讨厌的东西,并且由个人来选择其生产是否适合。 Here is another switch-case implemented for Type, 太棒了。拥抱它或转身离开。不客气。。
  • @Xaisoft 不管是谁,特别是指任何人:)
  • 其中一个问题是,当您有太多选择时,您可能不知道该做什么。正如 Eric Lippert 所指出的那样,部分原因在于经验和知道什么是适合这项工作的工具。
  • @Xaisoft 我同意,你的问题也很相关。
【解决方案2】:

虽然这看起来很无辜,尤其是与立即执行代码的 ToList 调用结合使用时,我绝对不会在查询中修改任何内容:这个技巧非常不寻常,以至于它会绊倒你的读者程序,即使是有经验的人,尤其是如果他们以前从未见过。

foreach 循环没有任何问题 - 您可以使用 LINQ 执行此操作并不意味着您应该执行此操作。

【讨论】:

  • 我会将ForEach 用于单行语句,而不是用于需要花括号(多个语句)的内容。 foreach 确实在这里更好。
  • 你说得对,这让我很受挫:) 我也同意你的第二个说法。
  • @nawful,很多人觉得 lambdas 中的状态修改有点令人反感。
  • 但如果我确实使用了 ForEach,就可读性而言,这会是更好的选择吗?
  • @Xaisoft ForEach 可以更好地工作,但它不是 LINQ 的一部分:它是在 List<T> 上定义的,而不是在 IEnumerable<T> 上,所以我几乎可以肯定它是用记住修改的想法(当然,只要列表本身保持不变)。使用foreach 循环与List<T>.ForEach 是个人喜好问题。
【解决方案3】:

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

【讨论】:

  • 谢谢埃里克。知道正确方法的唯一方法是首先知道你做错了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 2023-01-11
相关资源
最近更新 更多