(精华)2020年8月11日 C#基础知识点 yield迭代器的使用

(精华)2020年8月11日 C#基础知识点 yield迭代器的使用

基本使用

/// <summary>
    /// 含有yield的函数说明它是一个生成器,而不是普通的函数。当程序运行到yield这一行时,该函数会返回值,并保存当前域的所有变量状态;
    /// 等到该函数下一次被调用时,会从上一次中断的地方开始执行,一直遇到下一个yield, 程序返回值, 并在此保存当前状态; 如此反复,直到函数正常执行完成。
    /// 迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。
    /// 简单来说,迭代器模式使得你能够获取到序列中的所有元素 而不用关心是其类型是array,list,linked list或者是其他什么序列结构。
    /// 这一点使得能够非常高效的构建数据处理通道(data pipeline)--即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是LINQ的核心模式。
    /// 在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接 口,那么就能够被迭代;
    /// 调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是 数据序列中的一个位置记录。
    /// 迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。
    /// </summary>
    public class YieldShow
    {<!-- -->
        public void Show()
        {<!-- -->
            IEnumerable<int> iterable = this.CreateEnumerable();//1 不会直接执行
            //IEnumerator iterator = iterable.GetEnumerator();
            IEnumerator<int> iterator = iterable.GetEnumerator();
            Console.WriteLine("开始迭代");
            while (true)
            {<!-- -->
                Console.WriteLine("调用MoveNext方法……");
                Boolean result = iterator.MoveNext();//2 正式开启CreateEnumerable
                Console.WriteLine("MoveNext方法返回的{0}", result);
                if (!result)
                {<!-- -->
                    break;
                }
                Console.WriteLine("获取当前值……");
                Console.WriteLine("获取到的当前值为{0}", iterator.Current);
            }
            Console.ReadKey();
        }

        /// <summary>
        /// 普通获取数据
        /// </summary>
        /// <returns></returns>
        public IEnumerable<int> CommonMethod()
        {<!-- -->
            List<int> results = new List<int>();
            int counter = 0;
            int result = 1;

            while (counter++ < 10)
            {<!-- -->
                Thread.Sleep(1000);
                Console.WriteLine($"获取{counter}次数据");
                result = result * 2;
                results.Add(result);
            }
            return results;
        }
        /// <summary>
        /// yield获取数据
        /// </summary>
        /// <returns></returns>
        public IEnumerable<int> YieldMethod()
        {<!-- -->
            int counter = 0;
            int result = 1;
            while (counter++ < 10)
            {<!-- -->
                Thread.Sleep(1000);
                Console.WriteLine($"获取{counter}次数据");
                result = result * 2;
                yield return result;
            }
        }

        public IEnumerable<int> CreateEnumerable()
        {<!-- -->
            try
            {<!-- -->
                Console.WriteLine("{0} CreateEnumerable()方法开始", DateTime.Now);
                for (int i = 0; i < 5; i++)
                {<!-- -->
                    Console.WriteLine("{0}开始 yield {1}", DateTime.Now, i);
                    yield return i;
                    Console.WriteLine("{0}yield 结束", DateTime.Now);
                    if (i == 4)
                    {<!-- -->
                        yield break;//直接终结迭代  4会出现的,,
                    }
                }
                Console.WriteLine("{0} Yielding最后一个值", DateTime.Now);
                yield return -1;
                Console.WriteLine("{0} CreateEnumerable()方法结束", DateTime.Now);
            }
            finally
            {<!-- -->
                Console.WriteLine("停止迭代!");
            }
        }
    }

延迟加载实现原理

/// <summary>
    /// 1 迭代器模式 Iterator
    /// 2 .net里面的迭代器模式 yield return
    /// 3 解密linq to object的延迟查询,按需获取
    /// </summary>
    class Program
    {<!-- -->
        static void Main(string[] args)
        {<!-- -->
            try
            {<!-- -->
                #region Show
                {<!-- -->
                    Console.WriteLine("**********************");
                    YieldShow yieldShow = new YieldShow();
                    yieldShow.Show();

                    Console.WriteLine("**********************");
                    LinqExtendShow.Show();

                    Console.WriteLine("**********************");
                    CustomCollection collection = new CustomCollection();
                    List<int> intList = collection.GetData();
                    for (int i = 0; i < intList.Count(); i++)
                    {<!-- -->
                        Console.WriteLine(intList[i]);
                    }

                    Console.WriteLine("**********************");
                    foreach (var item in collection)
                    {<!-- -->
                        Console.WriteLine(item);//按需获取,延迟查询
                    }
                }
                //LinqExtendShow.Show();
                #endregion

            }
            catch (Exception ex)
            {<!-- -->
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }
    }
    /// <summary>
    /// 含有yield的函数说明它是一个生成器,而不是普通的函数。当程序运行到yield这一行时,该函数会返回值,并保存当前域的所有变量状态;等到该函数下一次被调用时,会从上一次中断的地方开始执行,一直遇到下一个yield, 程序返回值, 并在此保存当前状态; 如此反复,直到函数正常执行完成。
    /// 迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。简单来说,迭代器模式使得你能够获取到序列中的所有元素 而不用关心是其类型是array,list,linked list或者是其他什么序列结构。这一点使得能够非常高效的构建数据处理通道(data pipeline)
    /// --即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是LINQ的核心模式。
    /// 在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接 口,那么就能够被迭代;调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是 数据序列中的一个位置记录。迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。
    /// </summary>
    public class YieldShow
    {<!-- -->
        public IEnumerable<int> CreateEnumerable()
        {<!-- -->
            try
            {<!-- -->
                Console.WriteLine("{0} CreateEnumerable()方法开始", DateTime.Now);
                for (int i = 0; i < 5; i++)
                {<!-- -->
                    Console.WriteLine("{0}开始 yield {1}", DateTime.Now, i);
                    yield return i;
                    Console.WriteLine("{0}yield 结束", DateTime.Now);
                    if (i == 4)
                    {<!-- -->
                        yield break;//直接终结迭代,4会出现的.
                    }
                }
                Console.WriteLine("{0} Yielding最后一个值", DateTime.Now);
                yield return -1;
                Console.WriteLine("{0} CreateEnumerable()方法结束", DateTime.Now);
            }
            finally
            {<!-- -->
                Console.WriteLine("停止迭代!");
            }
        }

        /// <summary>
        /// MoveNext 检查是否存在  并设置current
        /// </summary>
        public void Show()
        {<!-- -->
            //不会直接执行
            IEnumerable<int> iterable = this.CreateEnumerable();
            //返回迭代器
            IEnumerator<int> iterator = iterable.GetEnumerator();
            Console.WriteLine("开始迭代");
            while (true)
            {<!-- -->
                Console.WriteLine("调用MoveNext方法……");
                Boolean result = iterator.MoveNext();//2 正式开启CreateEnumerable
                Console.WriteLine("MoveNext方法返回的{0}", result);
                if (!result)
                {<!-- -->
                    break;
                }
                Console.WriteLine("获取当前值……");
                Console.WriteLine("获取到的当前值为{0}", iterator.Current);
            }
            Console.ReadKey();
        }
    }

    public class Student
    {<!-- -->
        public int Id {<!-- --> get; set; }
        public int ClassId {<!-- --> get; set; }
        public string Name {<!-- --> get; set; }
        public int Age {<!-- --> get; set; }

        public void Study()
        {<!-- -->
            Console.WriteLine("{0} {1}是大神", this.Id, this.Name);
        }
    }

    public class LinqExtendShow
    {<!-- -->
        /// <summary>
        /// 准备数据
        /// </summary>
        /// <returns></returns>
        private static List<Student> GetStudentList()
        {<!-- -->
            #region 初始化数据
            List<Student> studentList = new List<Student>()
            {<!-- -->
                new Student()
                {<!-- -->
                    Id=1,
                    Name="打兔子的猎人",
                    ClassId=2,
                    Age=35
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="Alpha Go",
                    ClassId=2,
                    Age=23
                },
                 new Student()
                {<!-- -->
                    Id=1,
                    Name="白开水",
                    ClassId=2,
                    Age=27
                },
                 new Student()
                {<!-- -->
                    Id=1,
                    Name="狼牙道",
                    ClassId=2,
                    Age=26
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="Nine",
                    ClassId=2,
                    Age=25
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="Y",
                    ClassId=2,
                    Age=24
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="小昶",
                    ClassId=2,
                    Age=21
                },
                 new Student()
                {<!-- -->
                    Id=1,
                    Name="yoyo",
                    ClassId=2,
                    Age=22
                },
                 new Student()
                {<!-- -->
                    Id=1,
                    Name="冰亮",
                    ClassId=2,
                    Age=34
                },
                 new Student()
                {<!-- -->
                    Id=1,
                    Name="瀚",
                    ClassId=2,
                    Age=30
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="毕帆",
                    ClassId=2,
                    Age=30
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="一点半",
                    ClassId=2,
                    Age=30
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="小石头",
                    ClassId=2,
                    Age=28
                },
                new Student()
                {<!-- -->
                    Id=1,
                    Name="大海",
                    ClassId=2,
                    Age=30
                },
                 new Student()
                {<!-- -->
                    Id=3,
                    Name="yoyo",
                    ClassId=3,
                    Age=30
                },
                  new Student()
                {<!-- -->
                    Id=4,
                    Name="unknown",
                    ClassId=4,
                    Age=30
                }
            };
            #endregion
            return studentList;
        }

        public static void Show()
        {<!-- -->
            List<Student> studentList = GetStudentList();

            var result = studentList.Where(s => s.Age < 30);

            var list = studentList.TestWhere<Student>(s =>
            {<!-- -->
                Console.WriteLine("1234678");//迭代器的延迟
                return s.Age < 30;
            });

            foreach (var item in list)
            {<!-- -->
                Console.WriteLine($"Name={item.Name} Age={item.Age}");
            }
        }
    }

    public static class LinqExtend
    {<!-- -->
        public static IEnumerable<TSource> TestWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {<!-- -->
            if (source == null)
            {<!-- -->
                throw new Exception("source");
            }
            if (predicate == null)
            {<!-- -->
                throw new Exception("predicate");
            }

            return new EnumeratorIterator<TSource>(source, predicate);
        }
    }

    public class EnumeratorIterator<TSource> : IEnumerable<TSource>
    {<!-- -->
        private IEnumerable<TSource> source;
        private Func<TSource, bool> predicate;

        public EnumeratorIterator(IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {<!-- -->
            this.source = source;
            this.predicate = predicate;
        }

        public IEnumerator<TSource> GetEnumerator()
        {<!-- -->
            foreach (var item in this.source)
            {<!-- -->
                if (predicate(item))
                    yield return item;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {<!-- -->
            foreach (var item in this.source)
            {<!-- -->
                if (predicate(item))
                    yield return item;
            }
        }
    }

    /// <summary>
    /// 集合:数据结构和访问方法
    /// </summary>
    public class CustomCollection //: IEnumerable
    {<!-- -->
        /// <summary>
        /// 获取全部数据
        /// </summary>
        /// <returns></returns>
        public List<int> GetData()
        {<!-- -->
            List<int> intList = new List<int>();
            for (int i = 0; i < 10; i++)
            {<!-- -->
                intList.Add(this.Get());
            }
            return intList;
        }

        /// <summary>
        /// 遍历
        /// </summary>
        /// <returns></returns>
        public IEnumerator GetEnumerator()
        {<!-- -->
            for (int i = 0; i < 10; i++)
            {<!-- -->
                yield return Get();
            }
        }


        private int Get()
        {<!-- -->
            Thread.Sleep(1000);
            return DateTime.Now.Second;
        }

    }
posted @ 2020-12-31 09:24  不要摸我的腰  阅读(91)  评论(0编辑  收藏  举报