备注:
如果你在语句中使用 yield
,则意味着它所处的方法、运算符或 get
访问器是迭代器。
yield
语句的两种形式:
yield return <expression>;
yield break;
1.使用 yield return
语句可一次返回一个元素。可通过使用 foreach 语句或 LINQ 查询来使用从迭代器方法返回的序列
(如下面的这个例子,用for遍历就不行,报错: 无法将带[]的索引应用于 IEnumerable<int>类型的表达式)。
2.foreach
循环的每次迭代都会调用迭代器方法。 迭代器方法运行到 yield return
语句时,会返回一个 expression
,并保留当前在代
码中的位置。 下次调用迭代器函数时,将从该位置重新开始执行。
3.可以使用 yield break
语句来终止迭代。
迭代器方法
internal class Yield
{
// public static IEnumerable<int> Method1()
public static List<int> Method1()
{
List<int> newList = new List<int>();
int result = 1;
for (int i = 0; i < 10; i++)
{
result *= 2;
newList.Add(result);
}
return newList;
}
public static IEnumerable<int> Method2()
{
int result = 1;
for (int i = 0; i < 10; i++)
{
result *= 2;
yield return result;
}
}
}
static void Main(string[] args)
{
List<int> l1 = Yield.Method1();
IEnumerable<int> l2 = Yield.Method2();
foreach (var item in l1)
{
Write(item + " ");
}
WriteLine();
foreach (var item in l2)
{
Write(item + " ");
}
ReadKey();
}
get
访问器
public static IEnumerable<int> Property
{
get
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
}
}
static void Main(string[] args)
{
List<int> l1 = Yield.Method1();
IEnumerable<int> l2 = Yield.Method2();
foreach (var item in l1)
{
Write(item + " ");
}
WriteLine();
foreach (var item in l2)
{
Write(item + " ");
}
WriteLine();
foreach (var item in Yield.Property)
{
Write(item + " ");
}
ReadKey();
}
迭代器方法和 get 访问器
迭代器的声明必须满足以下要求:
-
返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。
返回 yield
或 IEnumerable 的迭代器的 IEnumerator 类型为 object
。 如果迭代器返回 IEnumerable<T> 或 IEnumerator<T>,则必须将 yield return
语句中的表达式类型隐式转换为泛型类型参数。
以下情形中不能包含 yield return
或 yield break
语句:
-
包含不安全的块的方法。
异常处理
不能将 yield return
语句置于 try-catch 块中。 可将 yield return
语句置于 try-finally 语句的 try 块中。
可将 yield break
语句置于 try 块或 catch 块中,但不能将其置于 finally 块中。
如果 foreach
主体(在迭代器方法之外)引发异常,则将执行迭代器方法中的 finally
块。
https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/yield
https://www.cnblogs.com/kingcat/archive/2012/07/11/2585943.html