写点什么

C#使用 yield 关键字提升迭代性能与效率

作者:EquatorCoco
  • 2025-01-22
    福建
  • 本文字数:2488 字

    阅读完需:约 8 分钟

前言


yield 关键字在 C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,减少了内存占用,并允许在迭代时执行复杂逻辑。


传统迭代和 yield 迭代方式对比


咱们来看看传统迭代方式和 yield 关键字迭代方式对比,是否如传说中的代码实现起来更简洁和高效:


        /// <summary>        /// 传统迭代方式和yield关键字迭代方式对比        /// </summary>        public static void IteratorComparisonRun()        {            Console.WriteLine("迭代器方法使用yield关键字:");            foreach (var number in GetNumbersWithYield())            {                Console.WriteLine(number);            }
            Console.WriteLine("传统迭代方法返回一个List<int>");            var numbers = GetNumbersWithoutYield();            foreach (var number in numbers)            {                Console.WriteLine(number);            }        }
        /// <summary>        /// 迭代器方法使用yield关键字        /// </summary>        /// <returns></returns>        public static IEnumerable<int> GetNumbersWithYield()        {            for (int i = 0; i < 6; i++)            {                yield return i;            }        }
        /// <summary>        /// 传统迭代方法返回一个List<int>        /// </summary>        /// <returns></returns>        public static List<int> GetNumbersWithoutYield()        {            var numbers = new List<int>();            for (int i = 0; i < 6; i++)            {                numbers.Add(i);            }            return numbers;        }
复制代码


输出结果:



yield 延迟加载按需获取数据


yield 关键字可以通过延迟执行的方式,仅在实际需要时生成数据,从而提高了性能和效率。


        /// <summary>        /// yield关键字延迟加载按需获取数据        /// </summary>        public static void LazyLoadingRun()        {            Console.WriteLine("yield延迟加载按需获取数据 开始...");
            foreach (var number in GetEvenNumbers(11))            {                Console.WriteLine($"返回值 === {number} ===");                Thread.Sleep(500);            }
            Console.WriteLine("yield延迟加载按需获取数据 结束...");        }
        /// <summary>        /// 使用yield返回偶数的迭代器方法        /// </summary>        /// <returns></returns>        public static IEnumerable<int> GetEvenNumbers(int number)        {            for (int i = 1; i < number; i++)            {                Console.WriteLine($"Yielding {i}");                if (i % 2 == 0)                {                    yield return i; //只在需要时生成偶数                }            }        }
复制代码


输出结果:



yield break 显式示迭代结束


yield break:显式示迭代结束,如以下示例所示:


        public static void YieldBreakRun()        {            Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] { 1, 3, 4, 5, -1, 3, 4 })));            //输出:1 3 4 5
            Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] { 9, 8, 7, 6, 5, -5, 88, 100 })));            //输出:9 8 7 6 5        }
        public static IEnumerable<int> TakeWhilePositive(IEnumerable<int> numbers)        {            foreach (int n in numbers)            {                if (n > 0)                {                    yield return n;                }                else                {                    yield break;                }            }        }
复制代码


什么情况不能使用 yield 关键字


  • 带有 in、ref 或 out 参数的方法。

  • Lambda 表达式和匿名方法。

  • 在 C# 13 之前,yield 在具有 unsafe 块的任何方法中都无效。从 C# 13 开始,可以在包含 unsafe 块的方法中使用 yield,但不能在 unsafe 块中使用。

  • 不能在 catch 和 finally 块中使用 yield return 和 yield break。

  • 不能在具有 catch 块的 try 块中使用 yield return 和 yield break。

  • 可以在只有 finally 块的 try 块中使用 yield return 和 yield break。


文章转载自:追逐时光者

原文链接:https://www.cnblogs.com/Can-daydayup/p/18684357

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

EquatorCoco

关注

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
C#使用yield关键字提升迭代性能与效率_C#_EquatorCoco_InfoQ写作社区