列表或数组实现立即加载所有项目,而 yield 实现提供延迟执行解决方案。
在实践中,通常希望根据需要执行最少量的工作,以减少应用程序的资源消耗。
例如,我们可能有一个应用程序处理来自数据库的数百万条记录。当我们在延迟执行拉式模型中使用 IEnumerable 时,可以获得以下好处:
- 可扩展性、可靠性和可预测性可能会提高,因为记录的数量不会显着影响应用程序的资源需求。
- 性能和响应能力可能会提高,因为处理可以立即开始,而不是等待首先加载整个集合。
- 由于应用程序可以停止、启动、中断或失败,因此可恢复性和利用率可能会提高。与仅使用实际使用的部分结果的预取所有数据相比,只会丢失正在进行的项目。
- 在添加恒定工作负载流的环境中可以进行连续处理。
这是先构建集合(例如列表)与使用产量的比较。
列表示例
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: Creating contact 1
Hello Bob
好的!当客户将项目从集合中“拉出”时,仅构建了第一个联系人。