ASP.NET(C#)
中的 yield
关键字吗?Yield return 会自动为您创建一个枚举器。
http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx
所以你可以这样做
//pseudo code:
while(get_next_record_from_database)
{
yield return your_next_record;
}
它允许您快速创建一个对象集合(一个枚举器),您可以循环遍历并检索记录。yield return语句处理了为您创建枚举器所需的所有代码。
yield return语句的重要部分是,在将集合返回给调用方法之前,您不必加载集合中的所有项目。它允许对集合进行惰性加载,因此您不必一次性付出访问代价。
何时使用Yield Return。
Yield 不仅仅是一种语法糖或者创建 IEnumerables 的简单方法。
如果需要更多信息,建议查看 Justin Etherage 的博客,其中有一篇很棒的文章介绍了 yield 的高级用法。
yield
是如何为你创建状态机时,你才能真正欣赏它的强大。它非常强大。 - Brian Gideonyield
是一种语法糖,可以在不必实现自己的类来实现这些接口的情况下,从方法中返回一个 IEnumerable<T>
或 IEnumerator<T>
对象。
IEnumerable<T>
的隐藏类,该类由yield return
语句提供数据。因此,在高层次上,它与实现自己的IEnumerable<T>
类、实例化并返回它没有什么不同。 - spoulsonyield
允许您在通常返回更具体类型(如 IList)的位置发出 IEnumerable。
这是一个非常好的例子,说明它如何简化您的代码并澄清您的意图。至于何时使用它,在页面上需要迭代集合的任何位置,您都可以使用返回 IEnumerable 的方法来替代 List/Dictionary 等。
我认为使用Stop和Continue模式(也称为yield/enumerators)的“优点”还没有得到充分阐述。所以让我来试试。
假设你有一个应用程序需要从数据库返回100万条记录。你有几种常见的做法:
通过使用yield模式,你只需一次将一个对象加载到内存中。此外,对象的消耗由遍历IEnumerator/IEnumerable代码的代码控制。这应该是一个典型的foreach代码块。
以下是一个示例,对比一下代码差异:
/// Bad Deadpool...
List<MyDbRecord> GetData(int page, int pageSize) {
using (var con = new DbContext()) {
// Option 1: Straight object grabbing
// return con.MyDbRecordSet.ToList();
// Option 2: Pagination Example
return con.MyDbRecordSet.Skip(page * pageSize).Take(pageSize).ToList();
// Option 3: DON'T TRY THIS AT HOME!
// var allTheRecords = con.MyDbRecordSet.ToList(); // Memory pressure
// System.IO.File.WriteAllText(
// "C:\\Windows\\Temp\\temp.json",
// JsonConvert.SerializeObject(allTheRecords)
// );// Large JSON Object dropped
}
}
/// Bad Deadpool...
IEnumerable<MyDbRecord> GetData(int page, int pageSize) {
using (var con = new DbContext()) {
// Option 1: Straight object grabbing
// return con.MyDbRecordSet.ToList();
// Option 2: Pagination Example
//return con.MyDbRecordSet.Skip(page * pageSize).Take(pageSize).ToList();
// Option 3: DON'T TRY THIS AT HOME!
// var allTheRecords = con.MyDbRecordSet.ToList(); // Memory pressure
// System.IO.File.WriteAllText(
// "C:\\Windows\\Temp\\temp.json",
// JsonConvert.SerializeObject(allTheRecords)
// );// Large JSON Object dropped
foreach (var i in con.MyDbRecordSet.AsNoTracking().AsQueryable()) {
yield return i; // Stream it vs buffering
}
}
}