写点什么

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

作者:追逐时光者
  • 2025-10-18
    广东
  • 本文字数:2520 字

    阅读完需:约 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://github.com/YSGStudyHards/DotNetGuide/tree/main/DotNetGuidePractice

参考文章

  • https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/statements/yield

发布于: 刚刚阅读数: 4
用户头像

不积跬步无以至千里,不积小流无以成江海! 2020-01-14 加入

微软MVP、华为云HCDE、华为云云享专家、51CTO专家博主、阿里云专家博主、博客园推荐博客、CSDN博客专家、腾讯云创作之星、掘金优秀创作者,一个热爱开源的全栈软件工程师,擅长C#、.NET、Vue等相关技术开发。

评论

发布
暂无评论
C#使用yield关键字提升迭代性能与效率_C#_追逐时光者_InfoQ写作社区