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

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

125次阅读
没有评论

共计 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、短信等云产品特惠热卖中