2012-03-01 80 views
5

我試圖更好地理解yield關鍵字,我認爲我對它有足夠的理解,所以我跑了一些測試,但是我被結果嚇倒了。瞭解yield關鍵字和LINQ

如果我運行下面的代碼中,我得到以下輸出這表明它循環的整個範圍不僅達數4

public void DoIt() 
    { 
     Console.WriteLine("Method Call"); 
     var results = GetData(Enumerable.Range(1, 10)); 
     Console.WriteLine("LINQ"); 
     var filtered = results.Where(x => x == 4); 
     Console.WriteLine("Start result loop"); 
     foreach (var item in filtered) 
     { 
       Console.WriteLine("Item is " + item); 
     } 
    } 

    private IEnumerable<int> GetData(IEnumerable<int> Input) 
    { 
     foreach (int item in Input) 
     { 
      if (item % 2 == 0) 
      { 
       Console.WriteLine("Found " + item); 
       yield return item; 
      } 
     } 
    } 

輸出:

Method Call 
LINQ 
Start result loop 
Found 2 
Found 4 
Item is 4 
Found 6 
Found 8 
Found 10 

如果我運行下面的代碼,它顯示它只能達到4,然後停止。

public void DoIt() 
    { 
     Console.WriteLine("Method Call"); 
     var results = GetData(Enumerable.Range(1, 10)); 
     Console.WriteLine("Start result loop"); 
     foreach (var item in results) 
     { 
      if (item == 4) 
      { 
       Console.WriteLine("Item is " + item); 
       break; 
      } 
     } 
    } 

    private IEnumerable<int> GetData(IEnumerable<int> Input) 
    { 
     foreach (int item in Input) 
     { 
      if (item % 2 == 0) 
      { 
       Console.WriteLine("Found " + item); 
       yield return item; 
      } 
     } 
    } 

輸出:

Method Call 
Start result loop 
Found 2 
Found 4 
Item is 4 

我想我不understading的東西,但它看起來好像LINQ是做什麼,我希望它反其道而行之?我雖然LINQ使用yield和延遲執行,我期望第二組代碼的結果對於第一組代碼是相同的。

+0

'Where'過濾結果,當項目滿足謂詞時,它不會停止返回結果。另一方面,當謂詞滿足時,你的手動'foreach'循環會中斷。 – 2012-03-01 11:26:02

回答

12

它使用延遲執行。 LINQ Where檢查輸入枚舉的所有元素,它在到達找到的第一個元素時不會停止。這就是First所做的。

如果您將Where更改爲First,或者如果您從第二個示例中刪除break,則第一個示例將返回與第二個示例相同的示例。

2

我想你的基本邏輯錯了,而不是LINQ。你的第一個例子必須迭代整個範圍,因爲where條件必須找到等於4的所有值,而不僅僅是等於4的第一個值。