C#中的yield

简介: C#中的yield

讲解

在 C# 基础库中经常可以看到很多方法返回值是 IEnumerable 类型,那么为什么返回 IEnumerable 而不是返回 IList、ICollection 或 List 类型呢?看完这篇文章你就能得到答案了。IEnumerable 它表示该集合中的元素可以被遍历,一般来说 IEnumerable 类型的对象会和yield紧密结合和。在 C# 中大部分方法是通过 return 语句把运行果返给调用者,同时把控制权也交回给了调用者。下面的代码将打印斐波拉契数据:

IEnumerable<int> fibonaccis= Fibonacci(10);
foreach (var f in fibonaccis)
{
    Console.Write("{0} ", f);
}
//计算斐波拉契数据
List<int> Fibonacci(int count)
{
  int p= 1;
  int c= 1;
  List<int> result = new List<int>();
  for (int i = 0; i < count; i++)
  {
    result.Add(p);
    int temp = p+ c;
    p= c;
    c= temp;
  }
  return result;
}

当我们在Console.Write() 打印结果之前,变量 fibonaccis计算出所有的数据了,运行代码后会把结果马上输出,这样的代码表面上看着没什么问题。那么我们换一个场景来想想,假设Fibonacci()方法内部每次计算得到下一个数都需要耗费较长的时间会出现什么情况,下面我们就来模拟所需的耗时,Fibonacci方法修改后的代码如下:

  for (int i = 0; i < count; i++)
  {
    result.Add(p);
    Thread.Sleep(3000);
    int temp = p + c;
    p = c;
    c= temp;
  }
  return result;
}

我们再次运行,在大概等待了3秒后马山就打印了数字。但是在等待的这段时间里我们没办法了解到程序运算的进展,运行过程中没有任何反馈的。如果要解决这个问题,我们可以通过 yield 关键字。yield 它可以把每一步的计算都推迟到程序实际需要的时候再执行,也就是说我们不用等所有结果都运行完才执行后续代码。下面的代码是我们使用 yield 关键字改造的 Fibonacci() 方法:

IEnumerable<int> Fibonacci(int count)
{
    int p= 1;
    int c= 1;
    for (int i = 0; i < count; i++)
    {
        yield return p;
        Thread.Sleep(3000);
        int temp = p + c;
        p = c;
        c = temp;
    }
}

运行代码后,会每隔 3 秒会输出一个数字直到输出所有数字。虽然说总等待时间是一样的,但对于部分程序来说这样总比让用户一直等着强。


总结

yield 关键字的用途是把指令的执行推迟到程序实际需要的时候,它可以使得我们更细致地控制集合每个元素产生的时机。好处是可以像上面演示的那样尽可能即时地给用户响应。还有一个好处是可以提高内存使用效率。通过 yield 返回的 IEnumerable 类型表示这是一个可以被遍历的数据集合。它之所以可以被遍历是因为它实现了一个标准的 IEnumerable 接口。我们把像上面这种包含 yield 语句并返回 IEnumerable 类型的方法称为迭代器(Iterator)。


tip:包含 yield 语句的方法的返回类型也可以是 IEnumerator<T>,它比迭代器更低一个层级,迭代器是列举器的一种实现。


迭代器方法和普通的方法相比,普通方法是通过 return 语句立即把程序的控制权交回给调用者,也把方法内的局部资源释放掉。迭代器方法则是依次返回多个值给调用者,并在这期间保留局部资源,等所有值都返回结束时再释放掉局部资源,这些返回的值将形成一组序列被调用者使用。

迭代器可以用于方法、属性或索引器中。迭代器中的 yield 语句分为两种:


  1. yeild return,把程序控制权交回调用者并保留本地状态,调用者拿到返回的值继续往后执行。
  2. yeild break,用于告诉程序当前序列已经结束,相当于正常代码块的 return 语句(迭代器中直接使用 return 是非法的)。


TIP:实际场景中一般很少写迭代器,因为大部分需要迭代的场景都是数组、集合和列表,这些类型内部已经封装好了所需的迭代器。


目录
相关文章
|
6月前
|
C#
C#学习相关系列之yield和return的区别
C#学习相关系列之yield和return的区别
|
6月前
|
SQL 开发框架 .NET
EntityFramework数据持久化复习资料3、C#拓展方法与yield关键字使用
EntityFramework数据持久化复习资料3、C#拓展方法与yield关键字使用
54 0
|
存储 开发框架 .NET
关于C# yield 你会使用吗?
假设有这样一个需求:在一个数据源(下面代码arry)中把其中大于4的数据取出来遍历到前台,怎么做?(不使用linq)
199 0
|
C# 编译器
C#:foreach语句,yield语句
原文:C#:foreach语句,yield语句 1. foreach语句 C#编译器会把foreach语句转换为IEnumerable接口的方法和属性。 1 foreach (Person p in persons) 2 { 3 Console.WriteLine(p); 4 } foreach语句会解析为下面的代码段。
1039 0
|
C# 编译器
C# yield return 用法与解析
原文:C# yield return 用法与解析 C# yield return 用法与解析 本文参考自:http://www.jb51.net/article/54810.htm    当初没有认真理解 yield 这个关键字,现在又遇到了依旧不理解,为了以后不再为了 yield 困惑,决定好好研究一下 yield 的用法与意义: yield 从字面上理解有“退位,屈服”的意思,转一下弯就理解成“权限转移”,也就是将控制权交给别人,在这里就是把集合里满足条件(如果没有过滤条件,就是全体)的个体的操作转移给另一个对象。
1736 0
|
C#
C#中yield return用法
转载:http://www.jb51.net/article/54810.htm         http://www.cnblogs.com/HunterWei/archive/2012/06/13/csharpyieldreturn.
850 0
|
13天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
28 3