2012-02-13 12 views
6

IEnumerableは延期するためにYieldを使用する必要がありますか?IEnumerableは延期するためにYieldを使用する必要があります

私は遅延実行と利回りを理解するのに役立つテストコードです。

//immediate execution 
     public IEnumerable Power(int number, int howManyToShow) 
     { 
      var result = new int[howManyToShow]; 
      result[0] = number; 
      for (int i = 1; i < howManyToShow; i++) 
       result[i] = result[i - 1] * number; 
      return result; 
     } 

     //deferred but eager 
     public IEnumerable PowerYieldEager(int number, int howManyToShow) 
     { 
      var result = new int[howManyToShow]; 
      result[0] = number; 
      for (int i = 1; i < howManyToShow; i++) 
       result[i] = result[i - 1] * number; 

      foreach (var value in result) 
       yield return value; 
     } 

     //deferred and lazy 
     public IEnumerable PowerYieldLazy(int number, int howManyToShow) 
     { 
      int counter = 0; 
      int result = 1; 
      while (counter++ < howManyToShow) 
      { 
       result = result * number; 
       yield return result; 
      } 
     } 

     [Test] 
     public void Power_WhenPass2AndWant8Numbers_ReturnAnEnumerable() 
     { 
      IEnumerable listOfInts = Power(2, 8); 

      foreach (int i in listOfInts) 
       Console.Write("{0} ", i); 
     } 


     [Test] 
     public void PowerYieldEager_WhenPass2AndWant8Numbers_ReturnAnEnumerableOfInts() 
     { 
      //deferred but eager execution 
      IEnumerable listOfInts = PowerYieldEager(2, 8); 

      foreach (int i in listOfInts) 
       Console.Write("{0} ", i); 
     } 


     [Test] 
     public void PowerYield_WhenPass2AndWant8Numbers_ReturnAnEnumerableOfIntsOneAtATime() 
     { 
      //deferred and lazy execution 
      IEnumerable listOfInts = PowerYieldLazy(2, 8); 

      foreach (int i in listOfInts) 
       Console.Write("{0} ", i); 
     } 
+0

あなたはclojureの構文を使うことができますし、同じことをするオブジェクトを書くこともできます。私は完全に質問に答えるための例を書くことを望んでいません。 –

答えて

6

それはyieldを使用するを持っていません - 最終的には、カスタム列挙子(IEnumerator[<T>])を書き込むと、最初MoveNext()までのアクションを遅延させることにより、yieldが行うすべてを行うことができます。しかし、それは実装するのがかなり苦痛です。確かにの場合の場合yieldを使用すると、実装はデフォルトで延期されます(yieldを使用しない場合はとなります)。のデータにアクセスすると、他の方法が使用されます列挙子を実装するためのイテレータブロック)絶対に必要な場合を除き

率直に言って、列挙子を書くことは難しいとバグがある、私はそれを避けるイテレータブロックは素晴らしいです

0

が延期と熱望して反対している - 。。。。怠惰単に延期の同義語です

熱心な配列は1つのwh ichはあらかじめ計算されています(リストや配列など)。遅延シーケンスとは、反復されるたびに計算されるものです。

例では、Powerは配列を計算してそれを返すので、熱心です。これは、IEnumerableが反復されるまで配列を構築しないPowerYieldEagerとは異なります。

あなたが延期対シーケンスの内容対シーケンスの可能性として熱心に考えることができます。これを念頭に置いて、yield returnは遅延の唯一の方法です。結果が要求されたときに計算されたシーケンスは、遅延シーケンスです。

+0

言語を明確にしてくれてありがとうBryan –

1

のIEnumerableがF2が延期される場合、F1は、F1とF2の両方があり、次のコードでは、例えば

を延期され、別の機能(F2)で計算のIEnumerableを返すことができる返す関数(F1)は延期

public IEnumerable<int> F2() 
{ 
    for (int i = 0; i < 10; i++) { 
     yield return i; 
    } 
} 

public IEnumerable<int> F1() 
{ 
    return F2(); 
} 
+0

面白いケース! –

+0

'F2が延期されている場合、F1は延期されます.':この特定のケースでは、常にそうとは限りません(http://stackoverflow.com/a/17817359/1443490を参照) – cheesemacfly

関連する問題