リストまたは配列の実装はすべてのアイテムをすぐにロードしますが、yield の実装は遅延実行ソリューションを提供します。
実際には、アプリケーションのリソース消費を削減するために、必要に応じて最小限の作業を実行することが望ましい場合がよくあります。
たとえば、データベースから数百万のレコードを処理するアプリケーションがあるとします。遅延実行プルベースのモデルで IEnumerable を使用すると、次の利点が得られます。
- レコード数はアプリケーションのリソース要件に大きな影響を与えないため、スケーラビリティ、信頼性、および予測可能性が向上する可能性があります。
- コレクション全体が最初にロードされるのを待つのではなく、すぐに処理を開始できるため、パフォーマンスと応答性が向上する可能性があります。
- アプリケーションは停止、開始、中断、または失敗する可能性があるため、回復可能性と使用率が向上する可能性があります。結果の一部のみを使用して実際に使用されたすべてのデータをプリフェッチする場合と比較して、進行中のアイテムのみが失われます。
- 一定のワークロード ストリームが追加される環境では、継続的な処理が可能です。
リストなどのコレクションを最初に作成する場合と、yield を使用する場合の比較を次に示します。
リストの例
public class ContactListStore : IStore<ContactModel>
{
public IEnumerable<ContactModel> GetEnumerator()
{
var contacts = new List<ContactModel>();
Console.WriteLine("ContactListStore: Creating contact 1");
contacts.Add(new ContactModel() { FirstName = "Bob", LastName = "Blue" });
Console.WriteLine("ContactListStore: Creating contact 2");
contacts.Add(new ContactModel() { FirstName = "Jim", LastName = "Green" });
Console.WriteLine("ContactListStore: Creating contact 3");
contacts.Add(new ContactModel() { FirstName = "Susan", LastName = "Orange" });
return contacts;
}
}
static void Main(string[] args)
{
var store = new ContactListStore();
var contacts = store.GetEnumerator();
Console.WriteLine("Ready to iterate through the collection.");
Console.ReadLine();
}
コンソール出力
ContactListStore: 連絡先 1 の作成
ContactListStore: 連絡先 2
ContactListStore: 連絡先 3
の作成 コレクションを反復処理する準備ができました。
注: リスト内の 1 つの項目を要求することさえせずに、コレクション全体がメモリに読み込まれました。
収量例
public class ContactYieldStore : IStore<ContactModel>
{
public IEnumerable<ContactModel> GetEnumerator()
{
Console.WriteLine("ContactYieldStore: Creating contact 1");
yield return new ContactModel() { FirstName = "Bob", LastName = "Blue" };
Console.WriteLine("ContactYieldStore: Creating contact 2");
yield return new ContactModel() { FirstName = "Jim", LastName = "Green" };
Console.WriteLine("ContactYieldStore: Creating contact 3");
yield return new ContactModel() { FirstName = "Susan", LastName = "Orange" };
}
}
static void Main(string[] args)
{
var store = new ContactYieldStore();
var contacts = store.GetEnumerator();
Console.WriteLine("Ready to iterate through the collection.");
Console.ReadLine();
}
コンソール出力
コレクションを反復する準備ができました。
注: コレクションはまったく実行されませんでした。これは、IEnumerable の「遅延実行」の性質によるものです。アイテムの作成は、本当に必要な場合にのみ行われます。
コレクションをもう一度呼び出して、コレクション内の最初の連絡先をフェッチするときの動作を逆にしてみましょう。
static void Main(string[] args)
{
var store = new ContactYieldStore();
var contacts = store.GetEnumerator();
Console.WriteLine("Ready to iterate through the collection");
Console.WriteLine("Hello {0}", contacts.First().FirstName);
Console.ReadLine();
}
コンソール出力
コレクション
ContactYieldStore を反復する準備ができました: 連絡先 1 の作成
Hello Bob
良い!クライアントがアイテムをコレクションから「引き抜いた」とき、最初の連絡先のみが構築されました。