什么是yield,使用yield在ASP.NET中有什么好处?

21
您能帮助我理解 ASP.NET(C#) 中的 yield 关键字吗?

6个回答

16

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


6

当然。只有当你完全理解yield是如何为你创建状态机时,你才能真正欣赏它的强大。它非常强大。 - Brian Gideon
该死,这太有帮助了。我知道这是旧的,但那篇文章真的对我有帮助。 - Terrance

1

我写了一个简单的示例,展示了在集合的访问周期中如何调用yield块。请点击这里查看。


1

yield 是一种语法糖,可以在不必实现自己的类来实现这些接口的情况下,从方法中返回一个 IEnumerable<T>IEnumerator<T> 对象。


是的,因为它与自己创建IEnumerable并返回不同。 - Jouke van der Maas
2
如果您使用.NET Reflector检查MSIL,您会发现C#创建了一个实现IEnumerable<T>的隐藏类,该类由yield return语句提供数据。因此,在高层次上,它与实现自己的IEnumerable<T>类、实例化并返回它没有什么不同。 - spoulson
由于将yield称为“语法糖”并不能完全涵盖其真正的潜力,您的回答可能会对他人造成伤害。如果有人读了这个回答后说:“我不会使用yield,它只是语法糖”,那该怎么办呢? - John Farrell

0

0

我认为使用Stop和Continue模式(也称为yield/enumerators)的“优点”还没有得到充分阐述。所以让我来试试。

假设你有一个应用程序需要从数据库返回100万条记录。你有几种常见的做法:

  1. 你可以返回一个包含100万个对象的集合,比如List或Array,但这会导致巨大的内存压力,可能会出现可怕的OutOfMemoryException。
  2. 你可以每次分页返回1000条记录,但这也有其缺点,因为现在你必须编写分页逻辑。
  3. 你可以将这些对象序列化到文件中,比如JSON或其他格式(这是我见过的最糟糕的想法)
  4. 你应该使用“yield”模式;与其他选项相比,它更像是流式传输对象。

通过使用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
      }
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接