下面的示例演示了 yield 语句的两种形式。
yield return <expression>; yield break;
使用 yield return 语句可一次返回一个元素。
通过 foreach 语句或 LINQ 查询来使用迭代器方法。 foreach 循环的每次迭代都会调用迭代器方法。 迭代器方法运行到 yield return 语句时,会返回一个 expression,并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。
可以使用 yield break 语句来终止迭代。
有关迭代器的详细信息,请参阅迭代器(C# 和 Visual Basic)。
迭代器的声明必须满足以下要求:
-
返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。
-
该声明不能有任何 ref 或out https://msdn.microsoft.com/zh-cn/library/t3c3bfhx.aspx 参数。
返回 IEnumerable 或 IEnumerator 的迭代器的 yield 类型为 object。如果迭代器返回 IEnumerable<T> 或 IEnumerator<T>,则必须将 yield return 语句中的表达式类型隐式转换为泛型类型参数。
你不能在具有以下特点的方法中包含 yield return 或 yield break 语句:
-
匿名方法。 有关详细信息,请参阅匿名方法(C# 编程指南)。
-
包含不安全的块的方法。 有关详细信息,请参阅unsafe(C# 参考)。
不能将 yield return 语句置于 try-catch 块中。 可将 yield return 语句置于 try-finally 语句的 try 块中。
yield break 语句可以位于 try 块或 catch 块,但不能位于 finally 块。
如果 foreach 主体(在迭代器方法之外)引发异常,则将执行迭代器方法中的 finally 块。
以下代码从迭代器方法返回 IEnumerable<string>,然后遍历其元素。
IEnumerable<string> elements = MyIteratorMethod();
foreach (string element in elements)
{
…
}
调用 MyIteratorMethod 并不执行该方法的主体。 相反,该调用会将 IEnumerable<string> 返回到 elements 变量中。
在 foreach 循环迭代时,将为 elements 调用 MoveNext 方法。 此调用将执行 MyIteratorMethod 的主体,直至到达下一个 yield return 语句。 yield return 语句返回的表达式不仅决定了循环体使用的 element 变量值,还决定了元素的 Current 属性(它是 IEnumerable<string>)。
在 foreach 循环的每个后续迭代中,迭代器主体的执行将从它暂停的位置继续,直至到达 yield return 语句后才会停止。 在到达迭代器方法的结尾或 yield break 语句时,foreach 循环便已完成。
示例
下面的示例包含一个位于 for 循环内的 yield return 语句。 Process 中的 foreach 语句体的每次迭代都会创建对 Power 迭代器函数的调用。 对迭代器函数的每个调用将继续到 yield return 语句的下一次执行(在 for 循环的下一次迭代期间发生)。
迭代器方法的返回类型是 IEnumerable(一种迭代器接口类型)。 当调用迭代器方法时,它将返回一个包含数字幂的可枚举对象。
public class PowersOf2
{
static void Main()
{
// Display powers of 2 up to the exponent of 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
示例
下面的示例演示一个作为迭代器的 get 访问器。 在该示例中,每个 yield return 语句返回一个用户定义的类的实例。
public static class GalaxyClass
{
public static void ShowGalaxies()
{
var theGalaxies = new Galaxies();
foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)
{
Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());
}
}
public class Galaxies
{
public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy
{
get
{
yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };
yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };
yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };
yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };
}
}
}
public class Galaxy
{
public String Name { get; set; }
public int MegaLightYears { get; set; }
}
}
有关更多信息,请参见C# 语言规范。 该语言规范是 C# 语法和用法的权威资料。