2016-05-13 4 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を使用する2番目の方法で発生します。最初のメソッドの出力は、列挙型の最初の値が生成されたときにのみ発生するため、2番目のメソッドの出力が最初に表示されます。

2番目のケースでは、実際に何かを列挙するのではなく、列挙されたときにのみ値を生成/フィルタリングするIEnumerableを返します。ただし、メソッド本体にはyield returnが含まれていないため、実際にはになります。と値を生成するIEnumerableは、通常の方法であり、期待どおりの順序で実行されます。

関連する問題