C# 中的迭代器





5.00/5 (6投票s)
本文简要介绍了 C# 中的迭代器。
引言
本文解释了什么是迭代器以及我们可以通过多少种方式实现迭代器。
背景
迭代器自 C# 的早期版本就可用。但开发者对迭代器的使用较少,也很少实现。在日常工作中,这个概念使用较少,也很少被实现。`yield` 在幕后为计算值生成一个状态机。如果查看编译后的代码,就可以看到这一点。另外需要注意的是,在迭代器中使用的 `Yield` 关键字提供了一种类似于 C# 中 LINQ 的延迟执行。
定义
引用迭代器是一种方法、get 访问器或运算符,它通过使用 `yield` 关键字对数组或集合类执行自定义迭代 -- 来自 M S D N
在方法中使用迭代器
让我们通过调用 `GetProducts()` 方法来返回产品的简单示例。
public class YieldInMethod
{
public static IEnumerable<string> GetProducts()
{
foreach (var item in Enumerable.Range(1,5))
{
yield return "Product" + item.ToString();
}
}
public static void Main(string[] args)
{
foreach(var item in GetProducts())
{
Console.WriteLine(item);
}
}
}
注意:在使用迭代器时,一个重要的点是迭代器的返回类型必须是 `IEnumerable`、`IEnumerator`、`IEnumerable<t>` 或 `IEnumerator<t>`。
发生了什么?
当在迭代器中第一次执行 `yield` return 语句时,它会立即从迭代器返回产品名称,并将“`Product1`”写入控制台。当再次调用迭代器方法时,它会从迭代器方法返回“`Product2`”,并将其写入控制台,依此类推。因此,对于第二次执行,它没有从方法返回“`Product1`”,而是返回了“`Product2`”,因为它知道自己离开的位置并恢复操作,从而返回第二个产品。
在 GET 访问器中使用迭代器
让我们稍微修改上面的代码,以便从 `get` 访问器返回产品和 ID。
public class YieldInGet
{
public IEnumerable<Products> GetProducts
{
get
{
yield return new Products() { Id = 1, Name = "Product1" };
yield return new Products() { Id = 2, Name = "Product2" };
yield return new Products() { Id = 3, Name = "Product3" };
}
}
public static void Main(string[] args)
{
YieldInGet yg = new YieldInGet();
foreach (Products p in yg.GetProducts)
{
Console.WriteLine(String.Format("Product Id: {0}, Name: {1}", p.Id, p.Name));
}
}
}
public class Products
{
public int Id { get; set; }
public string Name { get; set; }
}
当访问 `GetProducts` 属性时,该属性会一次返回一个产品的列表,其中包含产品的 ID 和名称。
在运算符中使用迭代器
`yield` 在运算符中的实现与 `yield` 在方法中的实现基本相同,只是这个实现使用运算符来返回值。让我们考虑一个简单的斐波那契数列示例,以演示在运算符中使用迭代器。
public class YieldInOperator
{
public static void Main(string[] args)
{
foreach (var item in Fibonacci(5))
{
Console.WriteLine(item);
}
}
public static IEnumerable<int> Fibonacci(int number)
{
int a = 0, b = 1;
yield return a;
yield return b;
for (int count = 0; count <= number; count++)
{
int temp = a;
a = b;
b = temp + b;
yield return b;
}
}
}
当调用 `Fibonnacci(5)` 时,将从 Fibonacci 方法返回“`a`”的值,然后是 `b`,然后是斐波那契数列的数字序列。
摘要
每当需要返回大量值的列表时,可以使用 `yield` 代替返回列表。