【发布时间】:2011-03-12 19:58:27
【问题描述】:
你能帮我理解asp .NET(C#)中的yield关键字吗?
【问题讨论】:
你能帮我理解asp .NET(C#)中的yield关键字吗?
【问题讨论】:
收益回报会自动为您创建一个枚举器。
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 语句的主要部分是在将集合返回给调用方法之前,您不必加载集合中的所有项目。它允许lazy loading 的集合,因此您不必一次性支付所有访问费用。
何时使用Yield Return。
【讨论】:
yield 用作语法糖以从方法返回 IEnumerable<T> 或 IEnumerator<T> 对象,而无需实现您自己的实现这些接口的类。
【讨论】:
IEnumerable<T> 的隐藏类,该类由 yield return 语句提供。所以,在高层次上,它与实现你自己的IEnumerable<T> 类,实例化并返回它没有什么不同。
yield 允许您发出 IEnumerable,您通常会在其中返回更具体的类型(如 IList)。
This is a pretty good example of how it can simplify your code and clarify your intent。至于您将在何处使用它,您需要在页面上迭代集合的任何地方都可以使用返回 IEnumerable 代替 List/Dictionary/etc 的方法。
【讨论】:
Yield 不仅仅是语法糖或创建 IEnumerables 的简单方法。
有关更多信息,我会查看 Justin Etherage 的博客 has a great article explaining more advanced usages of yield。
【讨论】:
yield。它非常强大。
我编写了一个简单的示例,展示了在集合的访问周期中如何调用 yield 块。看看here。
【讨论】:
我认为使用停止和继续模式(AKA yield/enumerators)的“好处”没有得到适当的阐述。那我试试吧。
假设您有一个应用需要从数据库中返回 100 万条记录。你有一些常见的做法:
通过使用产量模式,您一次只能将一个对象水合到内存中。此外,对象的使用由通过 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
}
}
}
【讨论】: