前言

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。

完整示例代码

参考文章

C#使用yield关键字提升迭代性能与效率的更多相关文章

  1. 使用C# yield关键字来提高性能和可读性

    对于”yield”这个关键字我已经见过N次了,直到最近我才知道这个关键字所蕴含的力量.我将在下面展示出一些使用”yield”让你的代码有更高可读性和更好性能的例子. 为了让你对yield有一些快速概览 ...

  2. 使用yield关键字来提高性能

    比如我们在开发当中往往会遇到这样的问题: public List<string> FindBobs(string [] names)   { List<string> bobs ...

  3. 从range和xrange的性能对比到yield关键字(中)

    上节提出了range和xrange的效率问题,这节我们来探究其中的原因   yield的使用   我们看下面的程序: #coding: utf-8 def test(): print 4 print ...

  4. Python:容器、迭代对象、迭代器、生成器及yield关键字

            在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...

  5. 从yield关键字看IEnumerable和Collection的区别

    C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的.相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”机制.但是即使你知道这个机制,你也很容易 ...

  6. C#的yield关键字

    using System; using System.Collections.Generic; using System.Reflection; using System.Text.RegularEx ...

  7. php yield关键字以及协程的实现

    php的yield是在php5.5版本就出来了,而在初级php界却很少有人提起,我就说说个人对php yield的理解 Iterator接口 在php中,除了数组,对象可以被foreach遍历之外,还 ...

  8. (转) Python Generators(生成器)——yield关键字

    http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...

  9. 转载yield关键字理解

    实现IEnumerable接口及理解yield关键字   [摘要]本文介绍实现IEnumerable接口及理解yield关键字,并讨论IEnumerable接口如何使得foreach语句可以使用. 本 ...

  10. HHVM 是如何提升 PHP 性能的?

    背景 HHVM 是 Facebook 开发的高性能 PHP 虚拟机,宣称比官方的快9倍,我很好奇,于是抽空简单了解了一下,并整理出这篇文章,希望能回答清楚两方面的问题: HHVM 到底靠谱么?是否可以 ...

随机推荐

  1. P4253 SCOI2015 小凸玩密室

    P4253 SCOI2015 小凸玩密室 一道紫色的 dp. 思路 首先读题: 要保证任意时刻所有被点亮的灯泡必须连通 在点亮一个灯泡后必须先点亮其子树所有灯泡才能点亮其他灯泡 考虑设 \(g[u][ ...

  2. Mobexterm 串口换行错误

    问题描述 使用 Mobexterm 连接串口时,在回显中存在换行错误问题,严重影响阅读串口数据. 解决方法 在左侧操作窗口中右击发生 换行错误问题 的窗口,比如我需要右击 COM9 右击后,在下拉列表 ...

  3. Nuxt.js 应用中的 webpack:error 事件钩子

    title: Nuxt.js 应用中的 webpack:error 事件钩子 date: 2024/11/25 updated: 2024/11/25 author: cmdragon excerpt ...

  4. JDK 7 中的 Fork/Join 模式

    轻松实现多核时代的并行计算 随着多核时代的来临,软件开发人员不得不开始关注并行编程领域.而 JDK 7 中将会加入的 Fork/Join 模式是处理并行编程的一个经典的方法.虽然不能解决所有的问题,但 ...

  5. Javascript 构造函数和类

    1.构造函数 含义:所谓"构造函数",就是专门用来生成实例对象的函数.它就是对象的模板,描述实例对象的基本结构.一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构 写法 ...

  6. 【前端】‘opencollective-postinstall‘ 不是内部或外部命令,也不是可运行的程序

    问题 'opencollective-postinstall' 不是内部或外部命令,也不是可运行的程序 解决办法 npm install --save opencollective-postinsta ...

  7. 设置QToolBar的Action图标之间的间隔

    设置QToolBar的Action图标之间的间隔,网上搜索一大堆没用的,原来非常简单. toolBar->layout()->setContentsMargins(10, 10, 10, ...

  8. 鸿蒙UI开发快速入门 —— part05:组件的样式复用

    1. 为什么要样式复用? 如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,样式的复用就很有必要了. 为此,鸿蒙推出了可 ...

  9. 那些年,我们一起追的 WLB

    2019年,那一年,我29岁. 那一年,"996是福报"的言论在网络上引发舆论轩然大波. 那一年,"大小周"."996"."007 ...

  10. Win10离线安装.NET Framework 3.5的方法技巧

    Win10离线安装.NET Framework 3.5的方法技巧 PC系统为win10,在使用过程中,曾遇到提示说 "你的电脑上的应用需要使用以下Windows功能:.NET Framewo ...