我遇到了一些像这样的代码:
Dim results = From item In New List(Of Integer) From {1, 2, 3}
Select item
Select item
我很惊讶Select item
两次是合法的。它似乎表现得与只有一条Select
行完全相同。我尝试转换为C#,它会产生编译错误。
有没有理由使用多个选择?这会导致查询行为不同吗?
答案 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允许这样做很好。