私は何をするか知ってyield
いますし、いくつかの例を見てきましたが、実際のアプリケーションについては考えられません.特定の問題を解決するためにそれを使用したことがありますか?
(理想的には、他の方法では解決できない問題)
実際、私は自分のサイト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 つは、特に複数のステップを実行し、各ステップで同じデータ セットを必要とするタスクの非同期プログラミングのメカニズムとして使用することです。この 2 つの例は、Jeffery Richters AysncEnumerator Part 1とPart 2です。Concurrency and Coordination Runtime (CCR) も、この手法CCR Iteratorsを利用します。
Enumerable クラスの LINQ の演算子は、yield ステートメントで作成される反復子として実装されます。通常はforeachステートメントを使用して、ループ内で列挙子を実際に使用するまで、実際には何も列挙せずに Select() や Where() などの操作を連鎖させることができます。また、コレクションの途中で停止することにした場合、IEnumerator.MoveNext() を呼び出したときに 1 つの値だけが計算されるため、すべての結果を計算するパフォーマンス ヒットを節約できます。
イテレータを使用して、式が必要な場合にのみ評価される他の種類の遅延評価を実装することもできます。また、コルーチンなどのより凝ったものにyieldを使用することもできます。
yield のもう 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);
}
yield を使用すると、具象型へのダウンキャストを防ぐことができます。これは、コレクションの消費者がコレクションを操作しないようにするのに便利です。
yield return
を使用して、一連の関数の結果をリストとして扱うこともできます。たとえば、従業員に 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);
}
}