首页 > 编程语言 >C#中的yield使用方法

C#中的yield使用方法

时间:2023-05-19 17:36:54浏览次数:29  
标签:return 调用者 迭代 C# IEnumerable yield int 方法

讲解
在 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;
}

 

我们再次运行,在大概等待了30秒后马山就打印了数字。但是在等待的这段时间里我们没办法了解到程序运算的进展,运行过程中没有任何反馈的。如果要解决这个问题,我们可以通过 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 语句分为两种:

yeild return,把程序控制权交回调用者并保留本地状态,调用者拿到返回的值继续往后执行。
yeild break,用于告诉程序当前序列已经结束,相当于正常代码块的 return 语句(迭代器中直接使用 return 是非法的)。
TIP:实际场景中一般很少写迭代器,因为大部分需要迭代的场景都是数组、集合和列表,这些类型内部已经封装好了所需的迭代器。

标签:return,调用者,迭代,C#,IEnumerable,yield,int,方法
From: https://www.cnblogs.com/itjeff/p/17415806.html

相关文章

  • SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息
    SpringBoot实现WebSocket发送接收消息+Vue实现SocketJs接收发送消息参考:1、https://www.mchweb.net/index.php/dev/887.html2、https://itonline.blog.csdn.net/article/details/81221103?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2......
  • LeetCode/子数组的最小值之和
    给定一个整数数组arr,找到min(b)的总和,其中b的范围为arr的每个(连续)子数组。1.单调栈假如要遍历所有区间,哪怕可以直接获得最小值,时间复杂度也是O(n2)这里我们不逐个找对应区间,而是计算每个值对区间的贡献,可以将时间复杂度降到O(n)其实也就找遍历时当前值的左边界和右边界,在......
  • disk-linux磁盘问题 unexpected output in sfdisk
    linux-disk磁盘问题unexpectedoutputinsfdisk问题:运行growpart/dev/vda1unexpectedoutputinsfdisk--version[sfdisk,来自util-linux2.23.2]解决方案:#运行以下命令切换ECS实例的字符编码类型,可能需要重启LANG=en_US.UTF-8#如果重启ECS实例后仍未......
  • 行云流水| CI 3.0 云原生构建全新上线
    研发过程中,如何直观且准确地获悉代码提交后的质量状态?引入持续集成,可以自动化的对代码进行代码检查、单元测试、编译构建、甚至部署与发布,大幅提升开发人员的效率。腾讯云CODING推出CI3.0——云原生构建,是一款基于代码仓库的构建工具,采用全新的设计理念。可用于持续集......
  • MySQL数据库远程连接开启方法
    1.先控制台进入mysql-uuser-ppassword2.在mysql控制台执行GRANTALLPRIVILEGESON*.*TO'username'@'%'IDENTIFIEDBY'password'WITHGRANTOPTION;(这里的username和password,单独在弄一个用户名和密码,别用root)3.然后再MySQL>FLUSHPRIVILEGES;......
  • xpath解析使用extract()的各种情况分析
    返回一个SelectorList对象 http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/selectors.html#selectorlistSelectorList类是内建list类的子类,提供了一些额外的方法:xpath(query)css(query)extract()re()__nonzero__()返回一个list(就是系统自带的那个)里面是一些你......
  • css li 不换行
    转载:感觉写的挺见解的,借鉴过来,以备后用。li不换行 ------不换行的策略: 不换行原理:ul和li默认都是display:block;的标签,可以通过2种方式实现li的不换行显示:*将li设为display:inline;,然后通过marging和padding设置li的间距,*将li设为float:left;,然后通过(......
  • 在ubuntu 下怎么将eclipse添加到应用,同时有可以通过终端打开。
    1:将ubuntu添加到应用程序的方法:在终端中敲入:sudogedit/usr/share/applications/Eclipse.desktop在打开的GEdit中输入以下文本[DesktopEntry]Name=EclipseComment=Eclipse3.42IDEExec=/usr/java/eclipse/eclipse   <—这里改成你的eclipse的安装位置Icon=/usr/java/ecli......
  • golang 只读chan 测试
    packagemainimport( "fmt" "time")funcmyGoroutine(stopCh<-chanstruct{}){ //在协程中监听停止信号 for{ select{ case<-stopCh: //接收到停止信号,执行清理操作并退出 fmt.Println("cleanup") return default: //继续正常的协程逻......
  • Sonarqube---You're not authorized to run analysis. Please contact the project ad
    问题:sonarqube执行时报错:You'renotauthorizedtorunanalysis.Pleasecontacttheprojectadministrator原因:项目开始执行是好的,因为需要做项目的权限控制,所以将project从public修改为private后,再执行就报You'renotauthorizedtorunanalysis.Pleasecontacttheproject......