列表或数组实现立即加载所有项目,而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
准备遍历集合。
注意:整个集合被加载到内存中,甚至不需要列表中的单个项目
产量示例
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
真好!当客户从集合中“拉出”该项目时,仅构造了第一个联系人。