使用" Select"的目的是什么?在这个LINQ查询中多次?

时间:2015-05-29 15:45:16

标签: vb.net linq

我遇到了一些像这样的代码:

Dim results = From item In New List(Of Integer) From {1, 2, 3}
              Select item
              Select item

我很惊讶Select item两次是合法的。它似乎表现得与只有一条Select行完全相同。我尝试转换为C#,它会产生编译错误。

有没有理由使用多个选择?这会导致查询行为不同吗?

3 个答案:

答案 0 :(得分:5)

C#等效语法为:

var results = from item in new List<int> {1, 2, 3}
              select item into item
              select item;

这样你就可以创建一个新的范围来“链接”查询或引用VB.Net文档(参见链接) Select子句为后续查询子句引入了一组新的范围变量(你可以看到C#关键字here或Select VB.Net子句documention以获取更多信息和示例)

答案 1 :(得分:4)

我不能说为什么这是允许的,但通过查看已编译的IL代码,您会看到该表达式最终会调用Enumerable.Select两次。

L_0021: ldftn int32 ConsoleApplication1.Module1::_Lambda$__1(int32)
L_0027: newobj instance void [mscorlib]System.Func`2<int32, int32>::.ctor(object, native int)
L_002c: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<int32, int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>)

L_0032: ldftn int32 ConsoleApplication1.Module1::_Lambda$__2(int32)
L_0038: newobj instance void [mscorlib]System.Func`2<int32, int32>::.ctor(object, native int)
L_003d: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<int32, int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, !!1>)

所以最后,查询等于:

Dim results = {1, 2, 3}.Select(Function(i) i).Select(Function(i) i)

答案 2 :(得分:3)

Sehnsucht和Bjørn-RogerKringsjå的答案是准确的。它的要点是您使用Select生成结果集,然后再次使用Select生成基于前一个结果集的新结果集。在您的示例中,两个结果集都是相同的,因此它与您仅使用Select一次相同。

要回答您的第二个问题,可能会出现一些情况,您希望使用多个Select编写查询以帮助提高可读性或出于其他原因。一个简单的例子可能如下所示:

Dim results = From item In New List(Of Integer) From {1, 2, 3}
              Where item > 1
              Select item
              Where item < 3
              Select item

这将返回仅包含整数2的集合。显然,这可以使用一个Select和一个Where(使用And)编写,但可能会出现一些情况您的条件非常复杂,您希望将它们拆分,而不是将它们作为单个Where子句的一部分。或者您可能还有其他事情需要将语句拆分为更小的部分。

一般来说,这种事情并没有多大用处,但如果你有需要,LINQ允许这样做很好。