2016-05-13 71 views
0

我想了解IEnumerator的收益率回報。在嘗試下面的簡單例子之後,我發現鏈中的最後一個方法首先執行。我並不期待。收益率返回改變鏈接調用方法的順序

public static void Example() 
    { 
     List<Pet> pets = 
       new List<Pet>{ new Pet { Name="Barley", Age=8 }, 
          new Pet { Name="Boots", Age=4 } 
          }; 

     var p1 = pets.ReturnPetAgeGreatThan2().ReturnPetAgeGreatThan4(); 

     foreach (var p in p1) 
     { 
      // Removed it to keep it simple 
      //Console.WriteLine("Pet Name:{0},Age:{1}", p.Name, p.Age); 
     } 

     Console.ReadLine(); 

    } 

    public static IEnumerable<Pet> ReturnPetAgeGreatThan2(this IEnumerable<Pet> p) 
    { 
     Console.WriteLine("I am in ReturnPetAgeGreatThan2"); 

     foreach (var par in p) 
     { 
      if (par.Age > 2) 
       yield return par; 
     } 
    } 

    public static IEnumerable<Pet> ReturnPetAgeGreatThan4(this IEnumerable<Pet> p) 
    { 
     Console.WriteLine("I am in ReturnPetAgeGreatThan4"); 

     foreach (var par in p) 
     { 
      if (par.Age > 4) 
       yield return par; 
     } 
    } 
} 

輸出

I am in ReturnPetAgeGreatThen4 
    I am in ReturnPetAgeGreatThen2 

但只要我刪除產量的回報,並更改功能,只使用return.The方法的調用秩序。

public static IEnumerable<Pet> ReturnPetAgeGreatThan2(this IEnumerable<Pet> p) 
    { 
     Console.WriteLine("I am in ReturnPetAgeGreatThen2"); 
     var result = p.Where(x => x.Age > 2); 

     return result; 
    } 

    public static IEnumerable<Pet> ReturnPetAgeGreatThan4(this IEnumerable<Pet> p) 
    { 
     Console.WriteLine("I am in ReturnPetAgeGreatThen4"); 
     var result = p.Where(x => x.Age > 4); 
     return result; 
    } 

輸出

 I am in ReturnPetAgeGreatThen2 
    I am in ReturnPetAgeGreatThen4 

任何幫助瞭解這將是大加讚賞。

回答

3

隨着yield return你正在創建一個隱式枚舉。在這種情況下,編譯器實際上做了很多代碼轉換。這裏的要點是,只要返回值就會保存方法的狀態

所以會發生什麼這裏基本上是你的第一個方法返回一個IEnumerable立即調用的時候,但代碼對於產生價值將尚未運行。只有枚舉時纔會發生這種情況。該枚舉發生在您的第二個方法中,該方法使用foreach。因此,您首先會看到第二個方法的輸出,因爲第一個方法的輸出僅在生成第一個來自enumerable的值時發生。

在你的第二種情況下,你實際上並沒有枚舉任何東西,而是返回IEnumerable,它只會在枚舉時生成/過濾值。但是,由於您的方法主體不再包含yield return,因此編譯器不再會將其重寫爲實際上IEnumerable,它會生成值,因此這只是一種常規方法,並且會按您期望的順序立即運行。