还是和以前一样,我先上代码,请大家先拿到我的代码或者你跟着敲,运行看效果,以及理解每行带代码的作用。
我们要带着为什么要用Yield这个关键字,不用可以吗这个目的去学知识,我相信会更加的有意思。

首先我贴出平时正常输出偶数集合的办法

/*
 *
 *  学习Yield Return 语法
 *  使用两个方法,显示1 - 100之间的全部偶数
 * 
 * 
 */

using System;
using System.Collections.Generic;


namespace YieldReturn语法解析
{
    class Program
    {
       static  private List<int> _numArray; //用来保存1-100 这100个整数

        Program() //构造函数。我们可以通过这个构造函数往待测试集合中存入1-100这100个测试数据
        {
            _numArray = new List<int>(); //给集合变量开始在堆内存上开内存,并且把内存首地址交给这个_numArray变量

            for (int i = 1; i <= 100; i++) 
            {
                _numArray.Add(i);  //把1到100保存在集合当中方便操作
            }
        }

        static void Main(string[] args)
        {
            new Program();

            TestMethod();


        }

        //测试求1到100之间的全部偶数
        static  public void TestMethod()
        {
            foreach (var item in GetAllEvenNumber()) 
            {
                Console.WriteLine(item); //输出偶数测试
            }
        }

        //测试我们正常情况下拿到全部偶数的方法
       static  IEnumerable<int> GetAllEvenNumber()
        {
            List<int> result = new List<int>(); //开集合内存存偶数用

            foreach (int num in _numArray) 
            {
                if(num % 2 == 0) //判断是不是偶数
                {
                    //yield return num;
                    result.Add(num); //存入集合
                }
            }

            //返回偶数集合变量   可能有人会觉得奇怪返回类型不是List<int>这样可以吗
            //这个就要回到我们的里氏替换原则了,子类是可以替换父类的,也就是当父类用
            //比如我这个方法是想得到IEnumerable<int> 类型变量,但是我给了List<int>类型变量
            //注意List<int> 是继承 IEnumerable<int> 的,什么意思当我们把子类当父类使用,
            //那么大才小用,因为子类很多都是继承父亲,你自身增加很多字段或者方法,这样就不能用了。
            return result;  
            //yield break;
        }


    }
}

贴出使用Yiele Return办法输出耦合集合

/*
 *
 *  学习Yield Return 语法
 *  使用两个方法,显示1 - 100之间的全部偶数
 * 
 * 
 */

using System;
using System.Collections.Generic;


namespace YieldReturn语法解析
{
    class Program
    {
       static  private List<int> _numArray; //用来保存1-100 这100个整数

        Program() //构造函数。我们可以通过这个构造函数往待测试集合中存入1-100这100个测试数据
        {
            _numArray = new List<int>(); //给集合变量开始在堆内存上开内存,并且把内存首地址交给这个_numArray变量

            for (int i = 1; i <= 100; i++) 
            {
                _numArray.Add(i);  //把1到100保存在集合当中方便操作
            }
        }

        static void Main(string[] args)
        {
            new Program();

            TestMethod();


        }

        //测试求1到100之间的全部偶数
        static  public void TestMethod()
        {
            foreach (var item in GetAllEvenNumber()) 
            {
                Console.WriteLine(item); //输出偶数测试
            }
        }

        //测试我们使用Yield Return情况下拿到全部偶数的方法
       static  IEnumerable<int> GetAllEvenNumber()
        {

            foreach (int num in _numArray) 
            {
                if(num % 2 == 0) //判断是不是偶数
                {
                    yield return num; //返回当前偶数

                }
            }        
            yield break;  //当前集合已经遍历完毕,我们就跳出当前函数,其实你不加也可以
            //这个作用就是提前结束当前函数,就是说这个函数运行完毕了。
        }


    }
}

大家测试了2个代码结果没,是不是都可以正确拿到全部偶数集合,具体我需要你们测,这样进步快,才会真是学会。只看不练假把戏。

现在我们说他们的区别:
这个才是真正要学的地方
我们需要下断点

这里写图片描述

我希望你是在断点调试,具体就贴太多,你会发现代码跑到Yield return num的时候,当前函数就会结束,并把这个num交给这里,我先上图

这里写图片描述

最终会给item变量。
然后输出,然后在执行 GetAllEvenNumber()方法,和上次得到偶数是一样。
我们发现这个Yield Return是可以让当前函数的进程状态切换到阻塞状态,然后去选择了把cpu交给当前的出进程,这样就转而执行调用方函数。 (补充个小知识点其实我们写的程序加入到内存中,并不定就是一个进程,我们会根据情况分成几个子进程去干活,方便操作系统去管理以及多道程序运行在内存,提高计算机资源的利用率)
这样有个好处,我们假如有1000000个数据,我们需要得到里面的耦合,当我们通过这个方法得到一个耦合会立马显示在控制台上。而不是等很久也就把全部偶数都查找到存入集合当中,然后在一一遍历输出。
这个好处是很大的。比如我们用户可能就看数据开始肯定不是全部值需要部分就可以,看完这些在看后面的,这样数据会让觉得显示没有延迟。

下面我们来断点调一般的查找偶数的函数

这里写图片描述

我们发现这个循环没有跑完是不会退出当前函数的,也就是必须要查找全部的偶数才可以。这样假如我们很多数据。就会一直等这个数据才可以拿到这个数据去显示给用户看。
这样就麻烦了。

因此我们下个结论:Yield Return关键字的作用就是退出当前函数,并且会保存当前函数执行到什么地方,也就上下文。你发现没下次执行这个函数上次跑来的代码是不会重复执行的,

但是你一般的return result 假如你在循环体提前return ,下面调这个函数是会从第一步开始重新执行的。不会记录上次执行的地方。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐