如何在 C# 中使用 yield
共 805字,需浏览 2分钟
·
2022-02-27 12:56
yield关键词是在 C# 2.0 中被引入的,我们都知道实现了 IEnumerable 接口的类都可以用于被 foreach 迭代,这是因为 IEnumerable 接口中提供了一个可迭代的 GetEnumerator()
方法,代码定义如下:
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
现在你也可以使用 yield 关键词来指定某些方法也是可以被迭代的,通常 C# 中有两种 yield 的语法格式:yield return
和 yield break
。
为什么要使用 yield 关键词
yield关键词可以实现一种 状态迭代
而不需要提前创建好一个临时集合,换句话说,当你在迭代器中使用 yield return
时,在数据返回之前你不需要创建一个临时集合来存储数据,你可以利用 yield return
一次返回集合中的一个元素,同时你也可以在方法和get访问器中使用带有迭代的 yield return
语句,值得注意的是,当每次执行 yield return
语句后,控制权都会转交给调用者。
说了这么多,如果有点懵的话,我们来看一个例子,下面的代码展示了如何使用 yield 关键词来返回 Fibonacci 数字,这个方法接收一个int类型的参数。
static IEnumerable<int> GenerateFibonacciNumbers(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<int> GenerateFibonacciNumbers(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 GetData(IEnumerable 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
。, IEnumerator,IEnumerator 在 yiled 的方法参数中不能使用 ref,out 标记。
不能将
yield return
和yield break
放在匿名方法中。不能将
yield return
和yield break
放在unsafe
方法中。
译文链接:https://www.infoworld.com/article/3122592/my-two-cents-on-the-yield-keyword-in-c.html