如何在 C# 中使用 yield

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在 C# 中使用 yield相关的知识,希望对你有一定的参考价值。

yield关键词是在 C# 2.0 中被引入的,我们都知道实现了 IEnumerable 接口的类都可以用于被 foreach 迭代,这是因为 IEnumerable 接口中提供了一个可迭代的 GetEnumerator() 方法,代码定义如下:


    public interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }

现在你也可以使用 yield 关键词来指定某些方法也是可以被迭代的,通常 C# 中有两种 yield 的语法格式:yield return <expression>yield break

为什么要使用 yield 关键词

yield关键词可以实现一种 状态迭代 而不需要提前创建好一个临时集合,换句话说,当你在迭代器中使用 yield return 时,在数据返回之前你不需要创建一个临时集合来存储数据,你可以利用 yield return 一次性返回集合中的每项数据,同时你也可以在方法和get访问器中使用带有迭代的 yield return 语句,值得注意的是,当每次执行 yield return 语句后,控制权都会转交给调用者。

说了这么多,如果有点懵的话,我们来看一个例子,下面的代码展示了如何使用 yield 关键词来返回 Fibonacci 数字,这个方法接收一个int类型的参数。


        static IEnumerable<intGenerateFibonacciNumbers(int n)
        {
            for (int i = 0, j = 0, k = 1; i < n; i++)
            {
                yield return j;
                int temp = j + k;
                j = k;
                k = temp;
            }
        }

上面的代码中 yield return j 在不退出 for 循环的情况下逐个返回斐波那契数,换句话说,这个迭代状态是被保留的,下面的代码展示了如何调用 GenerateFibonacciNumbers()


            foreach (int x in GenerateFibonacciNumbers(10))
            {
                Console.WriteLine(x);
            }

下面是仅供参考的完整代码。


    class Program
    {
        static void Main(string[] args)
        {
            foreach (int x in GenerateFibonacciNumbers(10))
            {
                Console.WriteLine(x);
            }
        }

        static IEnumerable<intGenerateFibonacciNumbers(int n)
        {
            for (int i = 0, j = 0, k = 1; i < n; i++)
            {
                yield return j;
                int temp = j + k;
                j = k;
                k = temp;
            }
        }
    }

也许你注意到了,上面的代码并没有创建一个 list 或者 array 去存放那些输出到控制台的斐波那契额数。

yield 关键词的另一个优点在于可以按需创建和返回你需要的数,下面的代码展示了 Get方法器 中仅返回 1-10 之间的偶数。


        public static IEnumerable<int> EvenNumbers
        {
            get
            {
                for (int i = 1; i <= 10; i++)
                {
                    if ((i % 2) == 0)
                        yield return i;
                }
            }
        }

你也可以使用 yield break 来提前中断一个迭代链,如下代码所示:


        public IEnumerable<T> GetData<T>(IEnumerable<T> items)
        {
            if (null == items)
                yield break;

            foreach (T item in items)
                yield return item;
        }

几点原则

当你在用 yield 时,请记住如下几点。

  • yield return 不能套在 try-catch 中,否则会报错。
  • yield break 不能放在 finally 中。

  • yield 方法的返回类型只能是 IEnumerable, IEnumerable<T>, IEnumerator,IEnumerator<T>

  • 在 yiled 的方法参数中不能使用 ref,out 标记。

  • 不能将 yield returnyield break 放在匿名方法中。

  • 不能将 yield returnyield break 放在 unsafe 方法中。

译文链接:https://www.infoworld.com/article/3122592/my-two-cents-on-the-yield-keyword-in-c.html


以上是关于如何在 C# 中使用 yield的主要内容,如果未能解决你的问题,请参考以下文章

C# 使用IEnumerable,yield 返回结果,同时使用foreach时,在循环内修改变量的值无效

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

由C# yield return引发的思考

C#中yield用法

yield(C# 参考)

C#中yield用法