yield用法

作用

在迭代器中返回下一个元素或者表示迭代结束

两种形式

1. yield return 表示返回迭代器下一个元素

写一个方法,求 2 3 2^{3} 23,分别用yield和普通的写法,来看一下区别

    // yield 写法
    static IEnumerable<int> Power1(int num, int exponet)
    {
        int result = 1;
        Console.WriteLine("yield 循环开始.");
        for (int i = 0; i < exponet; i++)
        {
            Console.WriteLine($"将要 yield {i}");
            result *= num;
            yield return result;
            Console.WriteLine($" 已经yield {i}");
        }
        Console.WriteLine("yield 循环结束.");
    }
        // 普通写法
    static IEnumerable<int> Power2(int num, int exponet)
    {
        List<int> list = new List<int>();
        int result = 1;
        Console.WriteLine("普通循环开始.");

        for (int i = 0; i < exponet; i++)
        {
            Console.WriteLine($"将要循环 {i}");
            result *= num;
            list.Add(result);
            Console.WriteLine($"已经循环 {i}");
        }
        Console.WriteLine("普通循环结束.");
        return list;
    }

调用方法

        #region yield return 返回下一个元素
        IEnumerable<int> result4 = Power1(2, 4);
        Console.WriteLine("hahah");
        foreach (var item in result4)
        {
            Console.WriteLine($"yield计算结果:{item}");
        }
        Console.WriteLine();

        IEnumerable<int> result5 = Power2(2, 4);
        Console.WriteLine("lalala");
        foreach (var item in result5)
        {
            Console.WriteLine($"普通计算结果---:{item}");
        }

        Console.ReadKey();
        #endregion

在这里插入图片描述

如结果所示,当开始对迭代器的结果进行迭代时,迭代器会一直执行,直到到达第一个 yield return 语句为止。 然后,迭代器的执行会暂停,调用方会获得第一个迭代值并处理该值。 在后续的每次迭代中,迭代器的执行都会在导致上一次挂起的 yield return 语句之后恢复,并继续执行,直到到达下一个 yield return 语句为止。 当控件到达迭代器或 yield break 语句的末尾时,迭代完成。

这里有个需要注意的点:power1()方法并不是立即被调用的。当代码执行到 IEnumerable<int> result4 = Power1(2, 4);时,并没有立刻调用Power1,而是到了下面的for循环时才调用的,这一点和普通写法的调用顺序是不一样的。普通写法时,当代码执行到 IEnumerable<int> result5 = Power2(2, 4);时会立即调用Power2方法。这一点可以通过运行结果里面打印hahaha和lalala的顺序直观的看出来。

2. yield break 表示迭代结束

        #region yield break 迭代结束
        Console.WriteLine(string.Join(" ", GetInts(new int[] { 1, 3, -5, 9 })));
        Console.WriteLine(string.Join(" ", GetInts(new int[] { 22, 44, 6, 8 })));
        #endregion

在这里插入图片描述
由上图可知,yield可以用于显示结束迭代。yield并不影响迭代的正常结束,当迭代到达末尾时,也可结束。

返回值类型

1. IEnumerable<T>

迭代器的返回类型为 IEnumerable<T>(在非泛型情况下,使用 IEnumerable 作为迭代器的返回类型)。
还可以使用 IAsyncEnumerable<T> 作为迭代器的返回类型。 这使得迭代器异步。 使用 await foreach 语句对迭代器的结果进行迭代,如以下示例所示:

await foreach (int n in GenerateNumbersAsync(5))
{
    Console.Write(n);
    Console.Write(" ");
}
// Output: 0 2 4 6 8

async IAsyncEnumerable<int> GenerateNumbersAsync(int count)
{
    for (int i = 0; i < count; i++)
    {
        yield return await ProduceNumberAsync(i);
    }
}

async Task<int> ProduceNumberAsync(int seed)
{
    await Task.Delay(1000);
    return 2 * seed;
}

2. IEnumerator<T>

迭代器的返回类型可以是 IEnumerator 或 IEnumerator。 在以下场景中实现 GetEnumerator 方法时,这非常有用:

  1. 设计实现 IEnumerable 或 IEnumerable 接口的类型。

  2. 添加实例或扩展GetEnumerator方法来使用 foreach语句对类型的实例启用迭代,如以下示例所示:

public static void Example()
{
    var point = new Point(1, 2, 3);
    foreach (int coordinate in point)
    {
        Console.Write(coordinate);
        Console.Write(" ");
    }
    // Output: 1 2 3
}

public readonly record struct Point(int X, int Y, int Z)
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return X;
        yield return Y;
        yield return Z;
    }
}

不可用情况

  1. 带有 in、ref 或 out 参数的方法
  2. Lambda 表达式和匿名方法
  3. 包含不安全的块的方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值