簡體   English   中英

我需要了解LINQ的幫助。 我的理解哪里出錯了?

[英]I need help understanding LINQ. Where is my understanding going wrong?

我會盡力讓您理解它,並且讓我知道我要去哪里了。

為了簡單起見,讓我們假設我們生活在一個只有

  • 12345
  • 運算符%>以通常的優先級

我想解釋我做什么

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);
}

我首先了解的是查詢本身不會創建Ienumerable<int> 它創建與查詢關聯的表達式樹 查詢所返回的元件yield在由編譯器創建的一個不可見的功能編等

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

(當然,這是一個奇怪的示例,因為Source.Reverse()本身是一個查詢,但是無論如何...)

現在我很困惑表達發辮在這里發揮作用的地方。 當我想到表達樹時,我想到了像

        (3 % 1 > 0)
          /      \ 
         /        \   
     (3 % 1)  >    0
      /   \ 
     3  %  1

在我創造的小世界中。 但是在我的LINQ查詢中,像這樣的樹在哪里起作用?

from i in All
where i % 2 == 1
orderby i descending
select i

??? 那是我不明白的。 我正在查看Expression類 ,我看到它如何創建我顯示的示例樹,但是我看不到它在查詢中的作用。

我會盡力讓您理解它,並且讓我知道我要去哪里了。

好。

我首先了解的是查詢本身不會創建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);

讓我們分解一下。 首先,編譯器將其轉換為

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);

接下來,編譯器執行重載解析並評估擴展方法

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);

接下來的lambda被刪除了:

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);

實際上,lambda的精確去除並不是這樣。 它們也會被緩存,但是讓我們忽略這個細節。

我認為您不希望將foreach廢止。 有關詳細信息,請參見C#規范。

如果您想知道Where和OrderBy的功能,請閱讀源代碼。

表達式樹不會在您的查詢中起作用,因為您的源是常規的內存列表。 –西奧多羅斯·查茲吉安娜基斯

這是真的。

沒有生成不可見的迭代器函數。 您的查詢翻譯為:

List<int> All = new List<int> { 1, 2, 3, 4, 5 };
IEnumerable<int> Filtered =
 All
 .Where(i => i % 2 == 0)
 .OrderByDescending(i => i);

不需要自定義迭代器。 該語言僅調用現有的庫函數。

對於IQueryable ,這是相同的,只是不將lambda參數作為委托而是作為表達式樹傳遞。

您可以通過在此處AsQueryable()調用中進行注釋來查看實際情況

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM