企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# yield(C# 参考) 如果你在语句中使用 **yield** 关键字,则意味着它在其中出现的方法、运算符或 **get** 访问器是迭代器。通过使用 **yield** 定义迭代器,可在实现自定义集合类型的 [IEnumerable](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerable.aspx) 和 [IEnumerator](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerator.aspx) 模式时无需其他显式类(保留枚举状态的类,有关示例,请参阅 [IEnumerator&lt;T&gt;](https://msdn.microsoft.com/zh-CN/library/78dfe2yb.aspx))。 下面的示例演示了 **yield** 语句的两种形式。 ``` yield return <expression>; yield break; ``` ## 备注 使用 **yield return** 语句可一次返回一个元素。 通过 [foreach](https://msdn.microsoft.com/zh-CN/library/ttw7t8t6.aspx) 语句或 LINQ 查询来使用迭代器方法。 **foreach** 循环的每次迭代都会调用迭代器方法。迭代器方法运行到 **yield return** 语句时,会返回一个 _expression_,并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。 可以使用 **yield break** 语句来终止迭代。 有关迭代器的详细信息,请参阅[迭代器(C# 和 Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dscyy5s0.aspx)。 ### 迭代器方法和 get 访问器 迭代器的声明必须满足以下要求: * 返回类型必须为 [IEnumerable](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerable.aspx)、[IEnumerable&lt;T&gt;](https://msdn.microsoft.com/zh-CN/library/9eekhta0.aspx)、[IEnumerator](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerator.aspx) 或 [IEnumerator&lt;T&gt;](https://msdn.microsoft.com/zh-CN/library/78dfe2yb.aspx)。 * 该声明不能有任何 [ref](https://msdn.microsoft.com/zh-CN/library/14akc2c7.aspx) 或out [https://msdn.microsoft.com/zh-CN/library/t3c3bfhx.aspx](https://msdn.microsoft.com/zh-CN/library/t3c3bfhx.aspx) 参数。 返回 [IEnumerable](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerable.aspx) 或 [IEnumerator](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerator.aspx) 的迭代器的 **yield** 类型为 **object**。如果迭代器返回 [IEnumerable&lt;T&gt;](https://msdn.microsoft.com/zh-CN/library/9eekhta0.aspx) 或 [IEnumerator&lt;T&gt;](https://msdn.microsoft.com/zh-CN/library/78dfe2yb.aspx),则必须将 **yield return** 语句中的表达式类型隐式转换为泛型类型参数。 你不能在具有以下特点的方法中包含 **yield return** 或 **yield break** 语句: * 匿名方法。有关详细信息,请参阅[匿名方法(C# 编程指南)](https://msdn.microsoft.com/zh-CN/library/0yw3tz5k.aspx)。 * 包含不安全的块的方法。有关详细信息,请参阅[unsafe(C# 参考)](https://msdn.microsoft.com/zh-CN/library/chfa2zb8.aspx)。 ### 异常处理 不能将 **yield return** 语句置于 try-catch 块中。可将 **yield return** 语句置于 try-finally 语句的 try 块中。 yield break 语句可以位于 try 块或 catch 块,但不能位于 finally 块。 如果 **foreach** 主体(在迭代器方法之外)引发异常,则将执行迭代器方法中的 **finally** 块。 ### 技术实现 以下代码从迭代器方法返回 **IEnumerable&lt;string&gt;**,然后遍历其元素。 ``` IEnumerable<string> elements = MyIteratorMethod(); foreach (string element in elements) { … } ``` 调用 MyIteratorMethod 并不执行该方法的主体。相反,该调用会将 **IEnumerable&lt;string&gt;** 返回到 elements 变量中。 在 **foreach** 循环迭代时,将为 elements 调用 [MoveNext](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerator.movenext.aspx) 方法。此调用将执行 MyIteratorMethod 的主体,直至到达下一个 **yield return** 语句。 **yield return** 语句返回的表达式不仅决定了循环体使用的 element 变量值,还决定了元素的 [Current](https://msdn.microsoft.com/zh-CN/library/58e146b7.aspx) 属性(它是 **IEnumerable&lt;string&gt;**)。 在 **foreach** 循环的每个后续迭代中,迭代器主体的执行将从它暂停的位置继续,直至到达 **yield return** 语句后才会停止。在到达迭代器方法的结尾或 **yield break** 语句时,**foreach** 循环便已完成。 下面的示例包含一个位于 **for** 循环内的 **yield return** 语句。 Process 中的 **foreach** 语句体的每次迭代都会创建对 Power 迭代器函数的调用。对迭代器函数的每个调用将继续到 **yield return** 语句的下一次执行(在 **for** 循环的下一次迭代期间发生)。 迭代器方法的返回类型是 [IEnumerable](https://msdn.microsoft.com/zh-CN/library/system.collections.ienumerable.aspx)(一种迭代器接口类型)。当调用迭代器方法时,它将返回一个包含数字幂的可枚举对象。 ``` 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# 语言规范](https://msdn.microsoft.com/zh-CN/library/ms228593.aspx)。该语言规范是 C# 语法和用法的权威资料。 ## 请参阅 [C# 参考](https://msdn.microsoft.com/zh-CN/library/618ayhy6.aspx) [C# 编程指南](https://msdn.microsoft.com/zh-CN/library/67ef8sbd.aspx) [foreach,in(C# 参考)](https://msdn.microsoft.com/zh-CN/library/ttw7t8t6.aspx) [迭代器(C# 和 Visual Basic)](https://msdn.microsoft.com/zh-CN/library/dscyy5s0.aspx)