解读 --- yield 关键字

这篇具有很好参考价值的文章主要介绍了解读 --- yield 关键字。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言

yield关键字是 C# 中的一种语言特性,用于在枚举器中简化迭代器的实现。它使得开发人员可以通过定义自己的迭代器来简化代码,而不必手动实现 IEnumerable 和 IEnumerator 接口。

使用 yield 关键字,可以将迭代器中的值一次一个地返回,而不必使用一个集合对象存储所有的值。当执行到yield return语句时,代码将会暂停执行,将返回值传递给迭代器的调用者,并将迭代器的状态保存下来。当下一次调用MoveNext方法时,代码将从之前的暂停点继续执行,直到遇到下一个yield return语句或者迭代器结束。

接下来探索一下 yield 的三种玩法:

初级

例如通过 yield 创建出一个 IEnumerable 以供 foreach 遍历,代码如下:

internal class Program
{
    static void Main(string[] args)
    {
        foreach (int i in EvenSequence(5, 18))
        {
            Console.Write(i + " ");
        }

        Console.ReadKey();
    }
    
    static IEnumerable<int> EvenSequence(int start, int end)
    {
        for (int i = start; i <= end; i++)
        {
            if (i % 2 == 0)
            {
                yield return i;
            }
        }
    }
}

在上面的代码中,我们定义了一个名为EvenSequence的方法,它返回一个实现了IEnumerable<int>接口的对象。在EvenSequence方法中,我们使用yield return语句来返回每个偶数值,并在每次暂停后保存方法的状态。

Main方法中,我们使用foreach循环语句来遍历EvenSequence方法返回的集合对象,并输出每个偶数值。由于我们使用了 yield 关键字,即使我们没有显式地实现IEnumerableIEnumerator接口,也能够遍历集合对象。

进阶

另一个方面,异步编程中也常常使用yield来创建异步生成器。使用yield创建异步生成器可以让我们轻松地以异步方式生成一系列值,而无需显式地管理异步状态。如以下代码:

public class Program
{
    public static void Main(string[] args)
    {
        AsynchronousIterate();

        Console.ReadLine();
    }

    public static async void AsynchronousIterate()
    {
        await foreach (var number in GenerateNumbersAsync())
        {
            Console.WriteLine(number);
        }
    }


    public static async IAsyncEnumerable<int> GenerateNumbersAsync()
    {
        for (int i = 0; i < 10; i++)
        {
            await Task.Delay(1000);

            yield return i;
        }
    }

}

上述代码定义了一个名为 GenerateNumbersAsync 的异步方法,该方法返回一个 IAsyncEnumerable<int> 类型的对象。在方法体中,我们使用一个 for 循环来生成一系列整数,并在每次迭代中异步等待1秒钟。紧接着,我们使用 yield return 语句将生成的整数返回给调用方。 要注意调用时使用异步迭代器(具有 await 关键字的foreach)来进行遍历>。

上述输出则是一秒输出一个结果,知道全部输出。

进阶举例场景

现在有这一样一个场景,有一大缸水,你手里有一个水瓢,,现在需要你把水缸里的水,全部移到另一个水缸。

前提条件:现在不知道缸里由具体多少水,也无法确定一瓢能舀多少,也无法确定你每一次舀水操作需要多长时间。

现在写一段代码,模拟这个过程。

拟定前提条件,如下代码:

static Random Random = new Random();

/// <summary>
/// 假设水缸能盛水90~100
/// </summary>
public static int GetOneWaterTankCapacity()
{
    return Random.Next(150, 200);
}

/// <summary>
/// 假设水瓢一次只能舀水2~5
/// </summary>
public static int GetOneWaterLadleCapacity()
{
    return Random.Next(2, 5);
}

/// <summary>
/// 模拟舀水所消耗的时间(0.5s~2S)
/// </summary>
/// <returns></returns>
public static async Task<int> ScoopingWater()
{
    await Task.Delay(Random.Next(500, 2000));
    return GetOneWaterLadleCapacity();
}

开始舀水,代码如下:

/// <summary>
/// 开始搬水
/// </summary>
/// <returns></returns>
public static async void MoveWater()
{
    //先确定缸里有多少水
    var WaterTankCapacity = GetOneWaterTankCapacity();

    await foreach (var item in CreateTasks(WaterTankCapacity))
    {
        Console.WriteLine($"这一瓢舀水量:{item.Result}\t{DateTime.Now}");
    }
    Console.WriteLine($"水全部舀完~\t{DateTime.Now}");
}

private static async IAsyncEnumerable<Task<int>> CreateTasks(int waterTankCapacity)
{
    int totle = 0;
    while (totle < waterTankCapacity)
    {
        Task<int> someWater = ScoopingWater();

        yield return someWater;

        totle += await someWater;
    }
}

最终会每次随机舀水,花费随机时间,水全部舀完。

输出:

这一瓢舀水量:4 2023/5/11 23:06:29
这一瓢舀水量:3 2023/5/11 23:06:30
这一瓢舀水量:2 2023/5/11 23:06:32
这一瓢舀水量:2 2023/5/11 23:06:34
这一瓢舀水量:3 2023/5/11 23:06:35
这一瓢舀水量:4 2023/5/11 23:06:36
这一瓢舀水量:2 2023/5/11 23:06:37
....
水全部舀完~     2023/5/11 23:07:27

通过上文例子,可以更深入理解 yield 创建的异步生成器。文章来源地址https://www.toymoban.com/news/detail-574584.html

总结

  • 使用 yield 关键字可以将一个方法转换为一个返回可枚举对象或迭代器的方法,而不必手动实现 IEnumerable 和 IEnumerator 接口
  • 使用 yield 来创建异步生成器,在某些场景下可以实现更高效、可靠的异步编程。

到了这里,关于解读 --- yield 关键字的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#中的`out`关键字

    C# 中的 out 是一个用来在方法调用时传递数据的修饰符。它允许你在方法内部创建一个临时的变量,用于接收传递进来的参数值,并在方法执行完毕后,将该变量的值返回给调用方法的对象。out 主要用于那些需要知道方法执行结果的参数上。 在 C# 中,out

    2024年02月22日
    浏览(66)
  • 谈谈mysql中的各个关键字

    mysql是当今最主流且 开放源码 的 关系型数据库 ,开发者为瑞典 MySQL AB 公司。目前 MySQL 被广泛地应用在 Internet 上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了 MySQL 作为网站数据库

    2024年04月24日
    浏览(40)
  • sql中的explain关键字用法

    在SQL中,使用 EXPLAIN 可以获取查询的执行计划,以便进行性能优化和查询调优。执行计划提供了关于查询操作的详细信息,涵盖了多个表头字段,每个字段都提供了特定的信息。以下是explain表头字段解释: id :每个操作的唯一标识符。这个字段通常是一个递增的整数

    2024年01月18日
    浏览(45)
  • 浅析Java中的final关键字(详细)

    1.什么是final(概念) 2.final基本用法 3.深入理解final 4.final 的最佳实践 谈到final,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final 。final 是 Java 中的一个,可以用于修饰类、方法和变量。当一个类被声明为

    2024年02月03日
    浏览(66)
  • Java中的volatile关键字实现原理

    在并发编程中,线程之间的可见性问题是非常重要的一项难题。Java中提供了一种解决并发可见性问题的机制,即volatile。 在本文中,我们将会讲解Java中volatile的实现原理,为什么它能够保证可见性,以及背后的实现原理涉及到的内存屏障和JVM屏障等内容。在学习

    2023年04月27日
    浏览(43)
  • 【JS】JavaScript中的this关键字

    目录 this是什么? this的指向 ①全局环境 ②构造函数 ③对象的方法 this的四类调用方式 ①作为对象方法调用 ②纯粹的函数调用 ③作为构造函数调用 ④使用apply、call、bind调用 举例说明 JavaScript  this  指的是它所属的对象。 它拥有不同的值,具体取决于它的使用位置:

    2024年02月14日
    浏览(46)
  • TypeScript 中的 type 关键字有什么用?

    创建类型别名 在 TypeScript 中,type 用于创建类型别名(Type Alias)。类型别名可以给一个类型起一个新的名字,使代码更具可读性和可维护性。 类型别名可以用于定义各种类型,包括基本类型、复合类型和自定义类型。通过 type ,可以为复杂的类型定义提供一个

    2024年02月08日
    浏览(41)
  • 使用less命令搜索文件中的关键字

    less 与 more 类似,less 可以随意浏览文件,支持翻页和搜索,支持向上翻页和向下翻页。 语法 less [参数] 文件 参数说明: -b 缓冲区大小 设置缓冲区的大小 -e 当文件显示结束后,自动离开 -f 强迫打开特殊文件,例如外围设备代号、目录和二进制文件 -g 只标志最后搜索的关键

    2024年02月12日
    浏览(63)
  • Python 中的==操作符 和 is关键字

    Python是一种功能强大的通用编程语言,提供了各种比较值和对象的方法。其中包括==操作符和is,它们的用途不同,但由于它们有时可以达到相同的目的,所以经常会被混淆。在本文中,我们将深入研究==和is之间的区别,探索它们如何工作以及何时适当地使用它们。

    2024年02月03日
    浏览(58)
  • 区块链智能合约solidity的中的一些关键字

    目  录 pragma mapping msg对象 block对象 contract constructor struct 数据地址 地址类型 address payable revert 以下场景使用 revert() : require 以下场景使用 require() : assert 以下场景使用 assert(): 访问权限 internal public private external function returns return view pure constant event emit modifier pragma   

    2024年01月16日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包