美文网首页
协程(四)yield与迭代器

协程(四)yield与迭代器

作者: 86a262e62b0b | 来源:发表于2019-10-28 14:59 被阅读0次

    协程(一)基本使用
    协程(二)协程什么时候调用
    协程(三)IEnumerable、IEnumerator、foreach、迭代
    协程(四)yield与迭代器
    协程(五)简单模拟协程
    协程(六)有关优化

    yield文档:
    https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/yield

    一.yield

    • 概念:yield上下文关键字,出现在一个方法、运算符(?)或get访问器 ,并且表明他们是一个迭代器。
    • 作用:使用yield,你不再需要像上一节那样,通过写一个类,并实现 IEnumerator<T>接口,来实现迭代器。

    yield语句两种形式:

    yield return <expression>;
    yield break;
    

    二. 迭代器方法

    1. 迭代器的声明必须满足以下要求:
    • 返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。
    • 声明不能有任何 in、ref 或 out 参数。
    1. 提示:
    • 返回 yield 或 IEnumerable 的迭代器的 IEnumerator 类型为 object。
    • 如果迭代器返回 IEnumerable<T> 或 IEnumerator<T>,则必须将 yield return 语句中的表达式类型隐式转换为泛型类型参数

    代码实现:

    IEnumerable<string> elements = MyIteratorMethod();
    foreach (string element in elements)
    {
       ...
    }
    
    理解:
    • 调用 MyIteratorMethod 不执行该方法的主体。 该调用会将IEnumerable<string> 返回到 elements 变量中。
    • 在 foreach 循环迭代时,将为 elements调用 MoveNext方法。 此调用将执行 MyIteratorMethod 的主体,直至到达下一个 yield return 语句。
    • yield return 语句返回的表达式不仅决定了循环体使用的 element 变量值,还决定了 elements 的 Current 属性(它是 IEnumerable<string>)。
    • 在 foreach 循环的每个后续迭代中,迭代器主体的执行将从它暂停的位置继续,直至到达 yield return 语句后才会停止。 在到达迭代器方法的结尾或 yield break语句时,foreach 循环完成。

    另外一个案例:

    public class PowersOf2
    {
        static void Main()
        {
            // Display powers of 2 up to the exponent of 8:
            foreach (int i in Power(2, 8))
            {
                Console.Write("{0} ", i);
            }
        }
    
        public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
        {
            int result = 1;
    
            for (int i = 0; i < exponent; i++)
            {
                result = result * number;
                yield return result;
            }
        }
    
        // Output: 2 4 8 16 32 64 128 256
    }
    

    三. 下面的示例演示一个作为迭代器的 get 访问器

    public static void ShowGalaxies()
    {
        var theGalaxies = new Galaxies();
        foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)
        {
            Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());
        }
    }
    
    public class Galaxies
    {
    
        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 class Galaxy
    {
        public String Name { get; set; }
        public int MegaLightYears { get; set; }
    }
    

    相关文章

      网友评论

          本文标题:协程(四)yield与迭代器

          本文链接:https://www.haomeiwen.com/subject/smfbvctx.html