使用后续子句与查询延续之间有什么区别?
通过后续的from子句,我的意思是使用构建查询的...from...in...from...in...select
模式。
关于查询延续和into
,this MSDN article说:
在后续查询中将一个查询的结果视为生成器通常很有用。
因此,into
关键字有助于我们将查询链接在一起,可以这么说。但是,似乎我们不需要into
关键字。相反,我们可以使用后续的from子句。但是,文章阐述了:
...使用into关键字在select或group子句之后拼接新的查询表达式。
因此,into
允许在拼接新查询之前使用select
或group
。这是使用查询延续而不是更简单的后续from子句的唯一原因吗?
例如,以下两个查询执行相同的操作。
https://dotnetfiddle.net/pwKcQU
using System;
using System.Collections;
using System.Linq;
public static class Program
{
public static void Main()
{
var array = new [] { "ab", "cd" };
var subsquentFromClause =
from first in array
from second in first
select second;
subsquentFromClause.Dump("Subsequent");
var queryContinuation =
from first in array select first into x
from second in x select second;
queryContinuation.Dump("Continuation");
}
public static void Dump(this IEnumerable query, string title)
{
Console.WriteLine("\n" + title);
foreach(var r in query)
{
Console.WriteLine(r);
}
}
}
答案 0 :(得分:2)
找出实际发生的事情的最好方法是使用像ILSpy这样的工具来反汇编代码并查看它。
查询表达式基本上是语法糖。它们是为了您的方便,然后转换为实际的函数调用。编译器将它们机械地转换为对IEnumerable<T>
扩展方法的一系列调用。例如,两个from
子句被转换为SelectMany
扩展方法,并带有该表达式的必需参数。
在这个特定的查询 - 延续案例中:
SelectMany
和SelectMany
可以访问投影x
,但first
将不再在范围内。生成的实际扩展方法链调用很难手动完成。最简单的方法是在ILSpy中查看它。
我甚至认为在转换中没有做任何优化,因为它是完全机械的。如果转换更加智能,则可以优化示例中的投影。
查看here以查看ILSpy反编译的一些实例。
例如,以下是您的查询的IL:
//Subsequent
System.String[]
.SelectMany (
first => first,
(first, second) => second
)
//Continuation
System.String[]
.Select (first => first)
.SelectMany (
x => x,
(x, second) => second
)