关闭

C# yield return 和 yield break

143人阅读 评论(0) 收藏 举报
分类:

    1. 在语句中使用 yield 关键字,表示在该关键字所在的方法、运算符或 get 访问器是迭代器。 通过使用 yield 定义迭代器,可在实现自定义集合类型的 IEnumerable 和 IEnumerator 模式时无需其他显式类

    2.yield return 用于返回IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>,一次返回一个元素。yield break用于终止循环遍历。

    3. 通过 foreach 语句或 LINQ 查询来使用迭代器方法。 foreach 循环的每次迭代都会调用迭代器方法。 迭代器方法运行到 yield return 语句时,会返回一个 expression,并保留当前在代码中的位置。 当下次调用迭代器函数时执行从该位置重新启动。
   4. 可以使用 yield break 语句来终止迭代。

   5.迭代器的声明必须满足以下要求:

    返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。

    该声明不能有任何 ref 或out参数。

    6.不能在具有以下特点的方法中包含 yield return 或 yield break 语句:

    匿名方法。
    包含不安全的块的方法

    7.异常处理:

     不能将 yield return 语句置于 try-catch 块中。 可将 yield return 语句置于 try-finally 语句的 try 块中。

    yield break 语句可以位于 try 块或 catch 块,但不能位于 finally 块。

    如果 foreach 主体(在迭代器方法之外)引发异常,则将执行迭代器方法中的 finally 块。

    8.举例:

    

      public static IEnumerable<int> Power1(int number, int exponent)
        {
            List<int> list = new List<int>();
            int result = 1;
            for (int i = 0; i < exponent; i++)
            {
                result = result * number;
                list.Add(result);
            }
            return list;
        }

       public static IEnumerable<int> Power2(int number, int exponent)
        {
            int result = 1;
            for (int i = 0; i < exponent; i++)
            {
                result = result * number;
                yield return result;
            }
        }

 static void Main(string[] args)
        {
            //IEnumerable<int> list = Power1(2, 8);
<pre name="code" class="csharp">            IEnumerable<int> list = Power2(2, 8);
 foreach (int l in list) { Console.WriteLine("{0}",l); } }


虽然2种方法的输出结果是一样的,但运作过程迥然不同。第一种方法,是把结果集全部加载到内存中再遍历;第二种方法,客户端每调用一次,yield return就返回一个值给客户端,是"按需供给"。

当调用power2时,并不立即执行该方法,在foreach循环时,将为list调用MonveNext方法,此时才执行Power2方法,知道下一个yield return语句,yield return语句返回的表达式不仅决定了循环体使用的l变量值,还决定了元素的Current属性值(它是IEnumerable<int>类型)。

使用yield return为什么能保证每次循环遍历的时候从前一次停止的地方开始执行呢?--因为,编译器会生成一个状态机来维护迭代器的状态。

9.总结:当希望获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就可以考虑使用yield return实现"按需供给"。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:107198次
    • 积分:2989
    • 等级:
    • 排名:第12133名
    • 原创:186篇
    • 转载:124篇
    • 译文:0篇
    • 评论:10条
    最新评论