阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

简单介绍C#中的yield关键字

332次阅读
没有评论

共计 3082 个字符,预计需要花费 8 分钟才能阅读完成。

导读 本文详细讲解了 C# 中的 yield 关键字,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

在 ”C# 中, 什么时候用 yield return” 中,我们了解到:使用 yield return 返回集合,不是一次性加载到内存中,而是客户端每调用一次就返回一个集合元素,是一种 ” 按需供给 ”。本篇来重温 yield return 的用法,探秘 yield 背后的故事并自定义一个能达到 yield return 相同效果的类,最后体验 yield break 的用法。

回顾 yield return 的用法

以下代码创建一个集合并遍历集合。

class Program
 {static Random r = new Random();
     static IEnumerable GetList(int count)
     {List list = new List();
         for (int i = 0; i 

使用 yield return 也能获得同样的结果。修改 GetList 方法为:

static IEnumerable GetList(int count)
{for (int i = 0; i 

通过断点调试发现:客户端每显示一个集合中的元素,都会到 GetList 方法去获取集合元素。

探密 yield

使用 yield return 获取集合,并遍历。

class Program
{public static Random r = new Random();
    static IEnumerable GetList(int count)
    {for (int i = 0; i 

生成项目,并用 Reflector 反编译可执行文件。在.NET 1.0 版本下查看 GetList 方法,发现该方法返回的是一个 GetList 类的实例。原来 yield return 是 ” 语法糖 ”,其本质是生成了一个 GetList 的实例。

简单介绍 C# 中的 yield 关键字

那 GetList 实例是什么呢?点击 Reflector 中 链接查看。

简单介绍 C# 中的 yield 关键字

  • 原来 GetList 类实现了 IEnumerable 和 IEnumerator 的泛型、非泛型接口
  • yield return 返回的集合之所以能被迭代、遍历,是因为 GetList 内部有迭代器
  • yield return 之所以能实现 ” 按需供给 ”,是因为 GetList 内部有一个_state 字段记录这上次的状态
  • 接下来,就模拟 GetList,我们自定义一个 GetRandomNumbersClass 类,使之能达到 yield return 相同的效果。

    using System;
    using System.Collections;
    using System.Collections.Generic;
    namespace ConsoleApplication2
    {
        class Program
        {public static Random r = new Random();
            static IEnumerable GetList(int count)
            {GetRandomNumbersClass ret = new GetRandomNumbersClass();
                ret.count = count;
                return ret;
            }
            static void Main(string[] args)
            {foreach(int item in GetList(5))
                    Console.WriteLine(item);
                Console.ReadKey();}
        }
        class GetRandomNumbersClass : IEnumerable, IEnumerator
        {
            public int count;// 集合元素的数量
            public int i; // 当前指针
            private int current;// 存储当前值
            private int state;// 保存遍历的状态
            #region 实现 IEnumerator 接口
            public int Current
            {get { return current;}
            }
            public bool MoveNext()
            {switch (state)
                {
                    case 0: // 即为初始默认值
                        i = 0;// 把指针调向 0
                        goto case 1;
                        break;
                    case 1:
                        state = 1;// 先设置原状态
                        if (!(i  GetEnumerator()
            {return this;}
            // 被显式调用的属性
            IEnumerator IEnumerable.GetEnumerator()
            {return GetEnumerator();
            }
            #endregion
        }
    }

    关于 GetRandomNumbersClass 类:

  • count 表示集合的长度,可以在客户端赋值。当调用迭代器的 MoveNext 方法,需要把 count 和当前位置比较,以决定是否可以再向前移动。
  • 字段 i 相当于索引,指针每次移动一位,i 需要自增 1
  • current 表示当前存储的值,外部通过 IEnumerator.Current 属性访问
  • 迭代器的 MoveNext 方法是关键:

  • state 字段是整型,表示产生集合过程中的 3 种状态
  • 当 state 为 0 的时候,说明是初始状态,把索引位置调到 0,并跳转到 state 为 1 的部分
  • 当 state 为 1 的时候,首先把状态设置为 1,然后判断索引的位置有没有大于或等于集合的长度,接着产生集合元素,把 state 设置为 2, 并最终返回 true
  • 当 sate 为 2 的时候,也就是迭代器向前移动一位,再次执行 MonveNext 方法的时候,跳转到 state 为 2 的语句块部分,把索引位置自增 1,再跳转到 state 为 1 的语句块中,产生新的集合元素
    如此循环
  • yield break 的用法

    假设在一个无限循环的环境中获取一个 int 类型的集合,在客户端通过某个条件来终止循环。

    class Program
    {static Random rand = new Random();
        static IEnumerable GetList()
        {while (true)
            {yield return rand.Next(100);
            }
        }
        static void Main(string[] args)
        {foreach (int item in GetList())
            {if (item%10 == 0)
                {break;}
                Console.WriteLine(item);
                 
            }
            Console.ReadKey();}
    }

    以上,当集合元素可以被 10 整除的时候,就终止循环。终止循环的时机是在循环遍历的时候。

    如果用 yield break, 就可以在获取集合的时候,当符合某种条件就终止获取集合。

    class Program
    {static Random rand = new Random();
        static IEnumerable GetList()
        {while (true)
            {int temp = rand.Next(100);
                if (temp%10 == 0)
                {yield break;}
                yield return temp;
            }
        }
        static void Main(string[] args)
        {foreach (int item in GetList())
            {Console.WriteLine(item);             
            }
            Console.ReadKey();}
    }
    总结:
  • yield return 能返回一个 ” 按需供给 ” 的集合
  • yield return 是 ” 语法糖 ”,其背后是一个实现了 IEnuerable,IEnumerator 泛型、非泛型接口的类,该类维护着一个状态字段,以保证 yield return 产生的集合能 ” 按需供给 ”
  • yield break 配合 yield return 使用,当产生集合达到某种条件的时候使用 yield break,以终止继续创建集合
  • 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值

    阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

    腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

    代金券:在阿里云专用满减优惠券

    正文完
    星哥玩云-微信公众号
    post-qrcode
     0
    星锅
    版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计3082字。
    转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
    【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
    阿里云-最新活动爆款每日限量供应
    评论(没有评论)
    验证码
    【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

    星哥玩云

    星哥玩云
    星哥玩云
    分享互联网知识
    用户数
    4
    文章数
    19351
    评论数
    4
    阅读量
    7994395
    文章搜索
    热门文章
    星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

    星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

    星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
    星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

    星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

    星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
    我把用了20年的360安全卫士卸载了

    我把用了20年的360安全卫士卸载了

    我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
    再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

    再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

    再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
    飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

    飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

    飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
    阿里云CDN
    阿里云CDN-提高用户访问的响应速度和成功率
    随机文章
    你的云服务器到底有多强?宝塔跑分告诉你

    你的云服务器到底有多强?宝塔跑分告诉你

    你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...
    还在找免费服务器?无广告免费主机,新手也能轻松上手!

    还在找免费服务器?无广告免费主机,新手也能轻松上手!

    还在找免费服务器?无广告免费主机,新手也能轻松上手! 前言 对于个人开发者、建站新手或是想搭建测试站点的从业者...
    【开源神器】微信公众号内容单篇、批量下载软件

    【开源神器】微信公众号内容单篇、批量下载软件

    【开源神器】微信公众号内容单篇、批量下载软件 大家好,我是星哥,很多人都希望能高效地保存微信公众号的文章,用于...
    再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

    再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

    再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
    星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

    星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

    星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...

    免费图片视频管理工具让灵感库告别混乱

    一言一句话
    -「
    手气不错
    你的云服务器到底有多强?宝塔跑分告诉你

    你的云服务器到底有多强?宝塔跑分告诉你

    你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...
    星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

    星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

      星哥带你玩飞牛 NAS-16:不再错过公众号更新,飞牛 NAS 搭建 RSS 对于经常关注多个微...
    星哥带你玩飞牛NAS硬件02:某鱼6张左右就可拿下5盘位的飞牛圣体NAS

    星哥带你玩飞牛NAS硬件02:某鱼6张左右就可拿下5盘位的飞牛圣体NAS

    星哥带你玩飞牛 NAS 硬件 02:某鱼 6 张左右就可拿下 5 盘位的飞牛圣体 NAS 前言 大家好,我是星...
    星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

    星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

      星哥带你玩飞牛 NAS-16:飞牛云 NAS 换桌面,fndesk 图标管理神器上线! 引言 哈...
    每天一个好玩的网站-手机博物馆-CHAZ 3D Experience

    每天一个好玩的网站-手机博物馆-CHAZ 3D Experience

    每天一个好玩的网站 - 手机博物馆 -CHAZ 3D Experience 一句话介绍:一个用 3D 方式重温...