zoukankan      html  css  js  c++  java
  • yield个人理解及简明示例

    1.写法有2种:
    yield return <expression>和yield break
    yield用于在迭代中返回一个值,并将值带入下一次迭代中。yield break则意味着停止迭代。纯粹的文字描述,一千个人有一千个说法,还是用代码更容易说清楚。
    2.官方示例(略带修改):

     private void button1_Click(object sender, EventArgs e)
            {
                string s = string.Empty;
                foreach (int i in List.Power(2,8))
                {
                    s += i.ToString() + ",";
                }
                MessageBox.Show(s);
            }
        public class List
        {
            //using System.Collections;
            public static IEnumerable Power(int number, int exponent)
            {
                int counter = 0;
                int result = 1;
                
                while (counter++ < exponent)
                {
                    result = result * number;
                    yield return result;
                }
            }
        }
    

    运行示例,发现power方法中的while代码部分,每循环执行一次,即输出一个值,并将这个值带入下一次循环,而power函数并没有每次被调用。

    为了验证,我们修改下官方示例代码,来看看我们的判断是否有误:

    private void button1_Click(object sender, EventArgs e)
            {
                string s = string.Empty;
                foreach (int i in List.Power())
                {
                    s += i.ToString() + ",";
                }
                MessageBox.Show(s);
            }
        public static IEnumerable Power()
            {
                int counter = 0;
                int result = 1;
                int number = 2, exponent = 8;
                while (counter++ < exponent)
                {
                    result = result * number;
                    yield return result;
                }
            }
    

     运行结果与官方示例相同,说明.net framework每次只把yield部分所在的部分代码进行了迭代返回处理。

    3.官方的另一个示例为用yield作为属性(输出方式略有修改)。

     private void button2_Click(object sender, EventArgs e)
            {
                var theGalaxies = new Galaxies();
                string ps = string.Empty;
                foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)
                {
                    ps += (theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString() + " >> ");
                }
                MessageBox.Show(ps);
            } 
    public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy
            {
                get
                {
                    yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };
                    yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };
                    yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };
                    yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };
                }
    
            }
    

     输出结果:

    从这个例子可以看出yield其实就是临时中断执行,输出后继续执行而已。

    可以修改下这个例子,看效果如何:

     public class Galaxies
        {
            List<Galaxy> ls = new List<Galaxy>();
            public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy
            {
                get
                {
                    yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };
                    yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };
                    yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };
                    yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };
                }
    
            }
            public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy1
            {
    
                get
                {
                    ls.Add(new Galaxy { Name = "Tadpole", MegaLightYears = 400 });
                    ls.Add(new Galaxy { Name = "Pinwheel", MegaLightYears = 25 });
                    ls.Add(new Galaxy { Name = "Milky Way", MegaLightYears = 0 });
                    ls.Add(new Galaxy { Name = "Andromeda", MegaLightYears = 3 });
                    int i = -1;
                    while (i++ < ls.Count - 1)
                    {
                        yield return ls[i];
                    }
                }
            }
        }
    

     调用NextGalaxy1后,结果与官方示例结果相同,还可以进一步修改NextGalaxy1,使其更容易别理解:

     public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy1
            {
    
                get
                {
                    ls.Add(new Galaxy { Name = "Tadpole", MegaLightYears = 400 });
                    ls.Add(new Galaxy { Name = "Pinwheel", MegaLightYears = 25 });
                    ls.Add(new Galaxy { Name = "Milky Way", MegaLightYears = 0 });
                    ls.Add(new Galaxy { Name = "Andromeda", MegaLightYears = 3 });
                    int i = 0;
                    while (i < ls.Count)
                    {
                        yield return ls[i];
                        i++;
                    }
                }
            }
    

     这样看来就很容易理解其含义了,更进一步说就是一边给你输出结果,一边继续给你执行代码,一举两得!

    如果想中断执行,则直接用yield break即可。

    代码如下:

     public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy1
            {
    
                get
                {
                    ls.Add(new Galaxy { Name = "Tadpole", MegaLightYears = 400 });
                    ls.Add(new Galaxy { Name = "Pinwheel", MegaLightYears = 25 });
                    ls.Add(new Galaxy { Name = "Milky Way", MegaLightYears = 0 });
                    ls.Add(new Galaxy { Name = "Andromeda", MegaLightYears = 3 });
                    int i = -1;
                    while (i++ < ls.Count - 1)
                    {
                        yield return ls[i];
                        if (ls[i].MegaLightYears == 0)
                        {
                            yield break;
                        }
    
                    }
                }
            }
    

     输出结果为:

    附官方链接:http://msdn.microsoft.com/zh-cn/library/9k7k7cf0.aspx

  • 相关阅读:
    Redis5设计与源码分析 (第17章 HyperLogLog相关命令的实现)
    Redis5设计与源码分析 (第16章 GEO相关命令)
    ES5和ES6函数的this指向
    vue响应式原理 (响应式并不等于数据双向绑定,千万不要混淆)
    vue中data为什么是函数而不是对象
    vue-enum 前端常量 枚举工具
    Vue3 写业务逻辑不适合用TS(TypeScript)
    vue-property-decorator vue3 ts 用的装饰器
    github git clone下载加速 && npm install 下载加速
    vue3 如果用ts,导出时候要用 defineComponent,这俩是配对的,为了类型的审查正确
  • 原文地址:https://www.cnblogs.com/jizhong/p/3809662.html
Copyright © 2011-2022 走看看