我需要帮助理解LINQ.我的理解在哪里出错了?

use*_*670 0 .net c# linq

我会尽力帮助你理解它,你让我知道我哪里出错了.

为简单起见,我们假设我们生活在一个只有的词中

  • 数字1,2,3,4,5
  • 运营商%,>他们通常的预防

我想解释当我这样做时会发生什么

List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = from i in All
                            where i % 2 == 1
                            orderby i descending
                            select i; 
foreach ( var i in Filtererd ) 
{
   Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)

我首先理解的是查询本身并没有创建Ienumerable<int>; 它创建与查询关联的表达式树.查询返回的元素yield在编译器创建的不可见函数中编辑

public static IEnumerable<int> MyInvisibleFunction ( List<int> Source )
{
    foreach ( int i in Source.Reverse() )
    {
       if ( i % 2 == 1 ) 
       {
           yield return i;
       } 
    }
} 
Run Code Online (Sandbox Code Playgroud)

(当然这是一个奇怪的例子,因为Source.Reverse()它本身就是一个查询,但无论如何...)

现在我很困惑表达发辫在这里发挥作用.当我想到表达树时,我会想到树木

        (3 % 1 > 0)
          /      \ 
         /        \   
     (3 % 1)  >    0
      /   \ 
     3  %  1
Run Code Online (Sandbox Code Playgroud)

在我创造的小世界里.但是,在我的LINQ查询中,这样的树会在哪里播放

from i in All
where i % 2 == 1
orderby i descending
select i
Run Code Online (Sandbox Code Playgroud)

??? 这就是我不明白的地方.我正在查看Expression类,我看到它如何创建我展示的示例树,但我看不出它会在我的查询中发挥作用.

Eri*_*ert 8

我会尽力帮助你理解它,你让我知道我哪里出错了.

好.

我首先理解的是查询本身并没有创建Ienumerable<int>;

这句话完全错了.

它创建与查询关联的表达式树.

这句话也完全错了.

查询返回的元素在编译器创建的不可见函数中生成

这句话也完全错了.

这样的树在我的LINQ查询中的位置

它没有.您的查询不使用表达式树.

我正在看Expression类,我看到它如何创建我展示的示例树,但我看不出它会在哪里发挥作用

它没有.

想要掩饰我做的事情

List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = from i in All
                        where i % 2 == 1
                        orderby i descending
                        select i; 
foreach ( var i in Filtererd ) 
  Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)

让我们分解吧.首先,编译器将其转换为

List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = All.Where(i => i % 2 == 1).OrderBy(i => i);                          
foreach ( var i in Filtererd ) 
  Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)

接下来,编译器会执行重载决策并评估扩展方法

List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = 
  Enumerable.OrderBy<int>(
    Enumerable.Where<int>(All, i => i % 2 == 1)), 
    i => i));                           
foreach ( var i in Filtererd ) 
  Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)

下一个lambdas是desugared:

static bool A1(int i) { return i % 2 == 1; )
static int A2(int i) { return i }
...
List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered = 
  Enumerable.OrderBy<int>(
    Enumerable.Where<int>(All, new Func<int, bool>(A1))), 
    new Func<int, int>(A2)));                           
foreach (var i in Filtererd ) 
  Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)

这实际上并不是羔羊如何完全被贬低; 它们也被缓存,但让我们忽略这个细节.

我假设你不希望foreach脱毒.有关详细信息,请参阅C#规范.

如果您想知道Where和OrderBy的作用,请阅读源代码.

  • 我想你的意思是在你的例子中使用`OrderByDescending`? (3认同)