LINQ编码如何工作?幕后发生了什么?

时间:2009-05-07 16:03:59

标签: linq clr

例如:

m_lottTorqueTools = (From t In m_lottTorqueTools _
                     Where Not t.SlotNumber = toolTuple.SlotNumber _
                     And Not t.StationIndex = toolTuple.StationIndex).ToList

这里出现了什么算法?在后台是否有嵌套的for循环?它是否为这些字段构建哈希表?我很好奇。

3 个答案:

答案 0 :(得分:6)

通常,查询表达式被转换为扩展方法调用。 (他们不 ,但99.9%的查询使用IEnumerable<T>IQueryable<T>。)

该方法的确切算法因方法而异。例如,您的示例查询不会使用任何哈希表,但加入或分组操作会这样做。

简单的Where调用在C#中转换为类似的东西(使用迭代器块,据我所知,目前在VB中不可用):

 public static IEnumerable<T> Where(this IEnumerable<T> source,
     Func<T, bool> predicate)
 {
     // Argument checking omitted
     foreach (T element in source)
     {
         if (predicate(element))
         {
             yield return element;
         }
     }
 }

谓词作为委托提供(如果使用IQueryable<T>,则为表达式树),并在序列中的每个项目上调用。流式传输结果和延迟执行 - 换句话说,直到您开始从结果中请求项目时才会发生任何事情,即使这样,它只会为了提供下一个结果而执行所需的操作。一些运算符不是延迟的(基本上是返回单个值而不是序列的运算符)和一些缓冲区输入(例如Reverse必须读取到序列的末尾才能返回任何结果,因为它读取的最后一个结果是它必须得到的第一个结果。

我担心每个LINQ运算符的详细信息都超出了单一答案的范围,但如果您对特定问题有疑问,我相信我们可以帮忙。

我应该补充一点,如果您使用的是LINQ to SQL或基于IQueryable<T>的其他提供程序,那么情况则完全不同。 Queryable类构建查询(在提供程序的帮助下,实现IQueryable<T>开始),然后查询通常由提供程序转换为更合适的形式(例如SQL)。确切的细节(包括缓冲,流式传输等)将完全取决于提供商。

答案 1 :(得分:1)

不仅取决于方法,还取决于使用的LINQ提供程序。在返回IQueryable<T>的情况下,LINQ提供程序会解释表达式树并按照它的喜好对其进行处理。

答案 2 :(得分:1)

LINQ一般会在幕后进行 lot 。对于任何查询,首先使用IQueryableProvider将其转换为表达式树,然后通常将查询编译为CIL代码,并生成指向此函数的委托,无论何时调用查询,您都会使用该委托。 。这是一个非常简化的概述 - 如果您想阅读有关该主题的精彩文章,我建议您查看How LINQ Works - Creating Queries。 Jon Skeet也在这个网站上向this question发布了一个很好的答案。