这两个LINQ查询可以互换使用吗?

4
a) 以下两个查询是否会产生相同的结果:
  var query1 = collection_1
            .SelectMany(c_1 => c_1.collection_2)
            .SelectMany(c_2 => c_2.collection_3)
            .Select(c_3 => c_3);

  var query2 = collection_1
            .SelectMany(c_1 => c_1.collection_2
            .SelectMany(c_2 => c_2.collection_3.Select(c_3 => c_3)));
b) 我认为这两个查询不能总是互换使用?例如,如果我们想要输出元素还包含c_1c_2的值,则只能使用query2,而不能使用query1
  var query2 = collection_1
            .SelectMany(c_1 => c_1.collection_2
            .SelectMany(c_2 => c_2.collection_3.Select(c_3 => new { c_1, c_2, c_3 } )));

?

Thank you


@vossad01:我打错字了,已经改正了。 - user1483278
2个回答

1

a. 这些查询是相等的,因为在两种情况下,你最终都会得到所有 c_3c_1c_2 中。

b. 你不能用这些查询来获取你所建议的 c_1c_2。如果你想要那样做,你需要使用 SelectManythis 过载。然而,“流畅”的语法相当笨拙。这通常是一个综合语法更好的例子:

from c_1 in colection_1
from c_2 in c_1.collection_2
from c_3 in c_2.collection_3
select new { c_1.x, c_2.y, c_3.z }

该死,我又搞错了。我写成了 c_3 => c_1, c_2, c_3,而不是 c_3 => new { c_1, c_2, c_3 }。请问,现在您知道这只是一个打字错误后,您的回答是否改变了? - user1483278
1
依然是同样的答案。没有结果选择器的 SelectMany 将第一个集合推出作用域。但我也打错了,应该使用另一种重载(已编辑)。 - Gert Arnold
1
“b. 您不能使用您建议的这些查询访问 c_1 和 c_2。” 您的查询是否实现了与 b) 查询相同的结果?也就是说,使用 b) 查询,即使在最内部的 SelectMany 语句中,c_1 和 c_2 也不会超出范围! - user1483278
1
是的,你说得对。对于一个没有编译器来跟踪括号的大脑来说确实很难 :) 更加喜欢查询语法的原因更多。 - Gert Arnold
更多喜欢查询语法的理由。我正在学习它的过程中,给我点时间吧 ;) - user1483278

1
您提供的代码片段似乎无效。c_3 未在 Select 语句的作用域内定义,所以除非我误解了什么,否则这段代码将无法编译。
看起来您正在尝试选择 collection_3 的元素,但是这是由 SelectMany 隐式完成的,因此两个查询中的最终 Select 语句都是多余的。将它们删除,两个查询就是等效的。
您只需要这个:
var query = collection_1
           .SelectMany(c_1 => c_1.collection_2)
           .SelectMany(c_2 => c_2.collection_3);

更新:x => x 是恒等映射,因此无论上下文如何,Select(x => x) 都是多余的。它的意思只是“对于序列中的每个元素,选择该元素”。

当然,第二个代码片段是不同的,SelectManySelect 语句确实需要嵌套才能选择所有三个元素 c_1c_2c_3

就像 Gert 所说的那样,您最好使用 查询语法。它更简洁,使得查询的工作更容易理解。


既然我已经编辑了我的帖子,那么在这两种情况下的最终选择语句都是多余的。你认为在 b) 中的最终选择仍然是多余的吗?(我认为 a) 中的最终选择是多余的。) - user1483278
那么,在尝试仅选择c_3作为输出时,a)下的查询确实可以互换使用(我确实理解在a)下的两个查询中Select是多余的)? - user1483278
1
是的。任何将元素映射到自身的Select子句都是本质上多余的,可以随时移除而不会产生任何影响。 - Will Vousden
最后一个问题,如果可以的话:既然我可以互换使用a)下的两个查询,那么选择其中一个而不是另一个是否有特定的原因(比如速度或代码清晰度等)? - user1483278
1
第一个对我来说更清晰,但除此之外,我认为没有太大的区别。查询推导式(正如Gert所演示的)几乎总是编写查询的更好方式,除非您需要使用它们不提供的功能。 - Will Vousden
谢谢你们的帮助,我很感激 - 我为打错字道歉,没有比我更沮丧的人了 :) - user1483278

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