2008-08-19 10 views
12

私はyieldのことを知っていますが、いくつかの例を見てきましたが、実際のアプリケーションを考えることはできません。収量の実際の用途は何ですか?

(他のいくつかの方法で解決できない理想的には、いくつかの問題)

答えて

8

私はこれが古い質問であることを認識しています(前のJon Skeet?)が、最近この質問を自分自身で検討しています。残念ながら、現在の回答は私の意見では、yieldステートメントの最も明白な利点は言及していません。

yieldステートメントの最大の利点は、標準リストを使用して、はるかに効率的なメモリ使用量で非常に大きなリストを反復処理できることです。

たとえば、100万行を返すデータベースクエリがあるとします。 DataReaderを使用してすべての行を取得してListに格納すると、list_size * row_sizeバイトのメモリが必要になります。

またはyield文を使用してIteratorを作成し、一度に1つの行だけをメモリに格納することができます。実際には、これにより大量のデータセットに対して「ストリーミング」機能を提供することができます。

また、Iteratorを使用するコードでは、単純なforeachループを使用し、必要に応じてループから抜け出すことができます。早期に中断した場合、最初の5行だけが必要な場合(たとえば)、データセット全体を強制的に取得する必要はありません。

について:

Ideally some problem that cannot be solved some other way 

yield文は、あなたが独自のカスタムイテレータの実装を使用して行うことができなかった何かを与えるものではありませんが、それはあなたが必要な多くの場合、複雑なコードを記述する必要が保存されます。 1つ以上の方法を解決できない問題は(もしあれば)ごくわずかです。あなたはまた、リストとして機能した結果、一連の治療にyield returnを使用することができます

Yield keyword value added?

Is yield useful outside of LINQ?

5

は、実際に私は私のサイトので、基本的な考え方を閲覧することは、現在であれば、それはチェックIdeaPipe

public override IEnumerator<T> GetEnumerator() 
{ 
    // goes through the collection and only returns the ones that are visible for the current user 
    // this is done at this level instead of the display level so that ideas do not bleed through 
    // on services 
    foreach (T idea in InternalCollection) 
     if (idea.IsViewingAuthorized) 
      yield return idea; 
} 

を上の非伝統的な方法でそれを使用します許可されていればそれはアイデアを返します。そうでない場合は、スキップされます。これにより、私はアイデアをキャッシュすることができますが、アイデアは依然として承認されたユーザーに表示されます。そうでなければ、1時間ごとに再ランク付けされたときに、アクセス許可に基づいて毎回引き出す必要があります。

1

EnumerableクラスのLINQの演算子は、yieldステートメントで作成されたイテレータとして実装されています。実際に列挙子をループ内で使用するまで、通常はforeachステートメントを使用するまで、Select()やWhere()などの操作を実際に列挙することなく連鎖させることができます。また、コレクションの中止を決定した場合は、IEnumerator.MoveNext()を呼び出すときに1つの値しか計算されないため、すべての結果を計算するとパフォーマンスが低下します。

イテレータは、式が必要なときにのみ評価される、他の種類の遅延評価を実装するためにも使用できます。また、コルーチンのようなもっと贅沢なものにはを使うこともできます。

1

収率のための別の良い使用は、IEnumerableの要素に機能を実行するために、異なるタイプの結果を返すために、例えばある:

public delegate T SomeDelegate(K obj); 

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action) 
{ 
    foreach (var i in list) 
     yield return action(i); 
} 
2

興味深い用途は、非同期プログラミングのための機構としてあります複数のステップを実行し、各ステップで同じデータセットを必要とするタスクの場合はesp。これの2つの例は、Jeffery Richters AysncEnumerator Part 1Part 2です。 Concurrency and Coordination Runtime(CCR)もこのテクニックを利用しますCCR Iterators

1

降伏を使用すると、具体的なタイプへのダウンキャスティングを防ぐことができます。これは、コレクションのコンシューマーがコレクションを操作しないようにするために便利です。

0

:ここ

は、より詳細な情報を提供し、より最近の質問と回答のカップルです。たとえば、2週間ごとに社員に報酬を支払う企業を考えてみましょう。このコードを使用して給与計算日のサブセットをリストとして取得することができます。

void Main() 
{ 
    var StartDate = DateTime.Parse("01/01/2013"); 
    var EndDate = DateTime.Parse("06/30/2013"); 
    foreach (var d in GetPayrollDates(StartDate, EndDate)) { 
     Console.WriteLine(d); 
    } 
} 

// Calculate payroll dates in the given range. 
// Assumes the first date given is a payroll date. 
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int  daysInPeriod = 14) { 
    var thisDate = startDate; 
    while (thisDate < endDate) { 
     yield return thisDate; 
     thisDate = thisDate.AddDays(daysInPeriod); 
    } 
} 
関連する問題