后续子句与查询继续

时间:2015-04-13 15:24:44

标签: c# linq

使用后续子句查询延续之间有什么区别?

通过后续的from子句,我的意思是使用构建查询的...from...in...from...in...select模式。

关于查询延续和intothis MSDN article说:

  

在后续查询中将一个查询的结果视为生成器通常很有用。

因此,into关键字有助于我们将查询链接在一起,可以这么说。但是,似乎我们不需要into关键字。相反,我们可以使用后续的from子句。但是,文章阐述了:

  

...使用into关键字在select或group子句之后拼接新的查询表达式。

因此,into允许在拼接新查询之前使用selectgroup。这是使用查询延续而不是更简单的后续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);
        }
    }
}

1 个答案:

答案 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
   )