yield 关键字向编译器指示它所在的方法是迭代器块。 编译器生成一个类来实现迭代器块中表示的行为。 在迭代器块中,yield 关键字与 return 关键字结合使用,向枚举器对象提供值。 这是一个返回值,例如,在 foreach 语句的每一次循环中返回的值。 yield 关键字也可与 break 结合使用,表示迭代结束。 有关迭代器的更多信息,请参见迭代器(C# 编程指南)。 下面的示例演示两种形式的 yield 语句。

 
  1. yield return <expression>;
  2. yield break;
备注

 

在 yield return 语句中,将计算 expression 并将结果以值的形式返回给枚举器对象;expression 必须可以隐式转换为 yield 类型的迭代器。

在 yield break 语句中,控制权将无条件地返回给迭代器的调用方,该调用方为枚举器对象的 IEnumerator.MoveNext 方法(或其对应的泛型 System.Collections.Generic.IEnumerable<T>)或 Dispose 方法。

yield 语句只能出现在 iterator 块中,这种块可作为方法、运算符或访问器的主体实现。 这类方法、运算符或访问器的体受以下约束的控制:

  • 不允许不安全块。

  • 方法、运算符或访问器的参数不能是 refout

  • yield return 语句不能放在 try-catch 块中的任何位置。 该语句可放在后跟 finally 块的 try 块中。

  • yield break 语句可放在 try 块或 catch 块中,但不能放在 finally 块中。

yield 语句不能出现在匿名方法中。 有关更多信息,请参见 匿名方法(C# 编程指南)

当和 expression 一起使用时,yield return 语句不能出现在 catch 块中或含有一个或多个 catch 子句的 try 块中。 有关更多信息,请参见 异常处理语句(C# 参考)

示例

 

在下面的示例中,迭代器块(这里是方法 Power(int number, int power))中使用了 yield 语句。 当调用 Power 方法时,它返回一个包含数字幂的可枚举对象。 注意 Power 方法的返回类型是 System.Collections.IEnumerable(一种迭代器接口类型)。

  1. public class List
  2. {
  3. //using System.Collections;
  4. public static IEnumerable Power(int number, int exponent)
  5. {
  6. int counter = 0;
  7. int result = 1;
  8. while (counter++ < exponent)
  9. {
  10. result = result * number;
  11. yield return result;
  12. }
  13. }
  14.  
  15. static void Main()
  16. {
  17. // Display powers of 2 up to the exponent 8:
  18. foreach (int i in Power(2, 8))
  19. {
  20. Console.Write("{0} ", i);
  21. }
  22. }
  23. }
  24. /*
  25. Output:
  26. 2 4 8 16 32 64 128 256
  27. */

有关更多信息,请参见 C# 语言规范。C# 语言规范是 C# 语法和用法的权威资料。

出处:https://msdn.microsoft.com/zh-cn/library/9k7k7cf0(v=vs.100).aspx

============================================================================

C# yield return 用法与解析

本文参考自:http://www.jb51.net/article/54810.htm

当初没有认真理解 yield 这个关键字,现在又遇到了依旧不理解,为了以后不再为了 yield 困惑,决定好好研究一下 yield 的用法与意义:

yield 从字面上理解有“退位,屈服”的意思,转一下弯就理解成“权限转移”,也就是将控制权交给别人,在这里就是把集合里满足条件(如果没有过滤条件,就是全体)的个体的操作转移给另一个对象。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. foreach (var item in FilterWithoutYield)
  6. {
  7. Console.WriteLine(item);
  8. }
  9. Console.ReadKey();
  10. }
  11.  
  12. //申明属性,定义数据来源
  13. public static List<int> Data
  14. {
  15. get
  16. {
  17. return new List<int>(){,,,,,,,};
  18. }
  19. }
  20.  
  21. //申明属性,过滤器(不适用yield)
  22. public static IEnumerable<int> FilterWithoutYield
  23. {
  24. get
  25. {
  26. var result = new List<int>();
  27. foreach (var i in Data)
  28. {
  29. if (i > )
  30. result.Add(i);
  31. }
  32. return result;
  33. }
  34. }
  35. }

可以看到如果不用yield,要返回大于4的所有的数,就要到另一个集合。而用yield的情况下就不必如此麻烦了:

  1. //申明属性,过滤器(使用yield)
  2. public static IEnumerable<int> FilterWithoutYield
  3. {
  4. get
  5. {
  6. foreach (var i in Data)
  7. {
  8. if (i > )
  9. yield return i;
  10. }
  11. }
  12. }

为什么会这样呢?

通过单步调试发现:

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

第一种方法,客户端调用过程大致为:

使用yield return,客户端调用过程大致为:

使用yield return为什么能保证每次循环遍历的时候从前一次停止的地方开始执行呢?

--因为,编译器会生成一个状态机来维护迭代器的状态。

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

出处:http://www.cnblogs.com/SilentCode/p/5014068.html

============================================================================================

yield是C#为了简化遍历操作实现的语法糖,我们知道如果要要某个类型支持遍历就必须要实现系统接口IEnumerable,这个接口后续实现比较繁琐要写一大堆代码才能支持真正的遍历功能。举例说明

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace

{
    class Program
    {
        static void Main(string[] args)
        {
            HelloCollection helloCollection = new HelloCollection();
            foreach (string s in helloCollection)
            {
                Console.WriteLine(s);
            }

Console.ReadKey();
        }
    }

//public class HelloCollection : IEnumerable
    //
{
    //
    public IEnumerator GetEnumerator()
    //
    {
    //
        yield return "Hello";
    //
        yield return "World";
    //
    }
    //}

    public class HelloCollection : IEnumerable
    {
        public IEnumerator GetEnumerator()
        {
            Enumerator enumerator = new Enumerator();
            return enumerator;
        }

public class Enumerator : IEnumerator, IDisposable
        {
            private int state;
            private object current;

public Enumerator(int state)
            {
                this.state = state;
            }

public bool MoveNext()
            {
                switch (state)
                {
                    case :
                        current = "Hello";
                        state = ;
                        return true;
                    case :
                        current = "World";
                        state = ;
                        return true;
                    case :
                        break;
                }
                return false;
            }

public void Reset()
            {
                throw new NotSupportedException();
            }

public object Current
            {
                get { return current; }
            }

            public void Dispose()
            {
            }
        }
    }
}

上面注释的部分引用了"yield return”,其功能相当于下面所有代码!可以看到如果不适用yield需要些很多代码来支持遍历操作。

yield return 表示在迭代中下一个迭代时返回的数据,除此之外还有yield break, 其表示跳出迭代,为了理解二者的区别我们看下面的例子

class A : IEnumerable
{
    private int[] array = new int[];

public IEnumerator GetEnumerator()
    {
        for (int i = ; i < ; i++)
        {
            yield return array[i];
        }
    }
}

如果你只想让用户访问ARRAY的前8个数据,则可做如下修改.这时将会用到yield break,修改函数如下

public IEnumerator GetEnumerator()
{
    for (int i = ; i < ; i++)
    {
        if (i < )
        {
            yield return array[i];
        }
        else
        {
            yield break;
        }
    }
}

这样,则只会返回前8个数据.

出处:http://www.cnblogs.com/kingcat/archive/2012/07/11/2585943.html

================================================================

在写两个demo代码看看

  1. static void Main(string[] args)
  2. {
  3. // Display the even numbers.
  4. Console.WriteLine("Even numbers");
  5. foreach (int i in GetEven())
  6. Console.WriteLine(i);
  7.  
  8. Console.WriteLine("===================");
  9.  
  10. // Display the odd numbers.
  11. Console.WriteLine("Odd numbers");
  12. foreach (int i in GetOdd())
  13. Console.WriteLine(i);
  14.  
  15. //aa();
  16. //kk();
  17. Console.ReadKey();
  18. }
  19.  
  20. public static int[] ints = { , , , , , , , , , , , , };
  21. public static IEnumerable<int> GetEven()
  22. {
  23. foreach (var item in ints)
  24. if (item % == )
  25. yield return item;
  26. }
  27. public static IEnumerable<int> GetOdd()
  28. {
  29. foreach (var item in ints)
  30. if (item % == )
  31. yield return item;
  32. }

出处:http://blog.csdn.net/joyhen/article/details/38703789

yield关键字用法与解析(C# 参考)的更多相关文章

  1. C# yield return 用法与解析

    原文:C# yield return 用法与解析 C# yield return 用法与解析 本文参考自:http://www.jb51.net/article/54810.htm 当初没有认真理解 ...

  2. C# 中yield关键字解析

    前言 前段时间了解到yield关键字,一直觉得还不错.今天给大家分享一下yield关键字的用法.yield return 返回集合不是一次性返回所有集合元素,而是一次调用返回一个元素.具体如何使用yi ...

  3. yield关键字的用法

    在上一篇文章中,说了下foreach的用法,但是还是比较复杂的,要实现接口才能进行遍历,有没有简单些的方法呢?答案是肯定的.且看下面. yield关键字的用法: 1.为当前类型添加一个任意方法,但是要 ...

  4. 解析Python中的yield关键字

    前言 python中有一个非常有用的语法叫做生成器,所利用到的关键字就是yield.有效利用生成器这个工具可以有效地节约系统资源,避免不必要的内存占用. 一段代码 def fun(): for i i ...

  5. yield关键字详解与三种用法

    本篇文章比较硬核, 适合有一定Python基础的读者阅读, 如果您对Python还不甚了解可以先关注我哦, 我会持续更新Python技术文章 yield详解 yield与return相同每次调用都会返 ...

  6. c# 递归 yield关键字的用法

    1.yield实现的功能 yield return: 先看下面的代码,通过yield return实现了类似用foreach遍历数组的功能,说明yield return也是用来实现迭代器的功能的. u ...

  7. C#中yield return用法分析

    这篇文章主要介绍了C#中yield return用法,对比使用yield return与不使用yield return的流程,更直观的分析了yield return的用法,需要的朋友可以参考下. 本文 ...

  8. C# 基础小知识之yield 关键字 语法糖

    原文地址:http://www.cnblogs.com/santian/p/4389675.html 对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味 ...

  9. C#中yield关键字理解

    yield关键字之前用得较少,但是在做项目开发的过程中也遇到了,当时有点迷惑,就顺便研究学习了一下,以下是个人理解,不到之处欢迎拍砖!废话就到这,上代码: class Program { static ...

随机推荐

  1. iOS项目开发优秀文章汇总

    UI界面 iOS和Android 界面设计尺寸规范  http://www.alibuybuy.com/posts/85486.html iPhone app界面设计尺寸规范  http://www. ...

  2. COS-2OS结构和硬件支持

    操作系统(Operating System,简称OS),是电子计算机系统中负责支撑应用程序运行环境以及用户操作环境的系统软件,同时也是计算机系统的核心与基石.它的职责常包括对硬件的直接监管.对各种计算 ...

  3. Linux上超酷的命令行扩展工具Oh My Zsh

    Oh My Zsh 是一款社区驱动的命令行工具,正如它的主页上说的,Oh My Zsh 是一种生活方式.它基于 zsh 命令行,提供了主题配置,插件机制,已经内置的便捷操作.给我们一种全新的方式使用命 ...

  4. GRE/GMAT/LSAT长难句300例精讲精练-思维导图

    <GRE/GMAT/LSAT长难句300例精讲精练>是GRE超人气名师陈琦老师团队的又一本新作,也是“再要你命3000”的新成员,从之前的词汇.短语.练习,提升到长难句层面,相信学完本书后 ...

  5. Spring_HelloWorld

    目录: 各个类文件: pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...

  6. Hive-行转列(explode)

    场景:通过parseHtml UDF解析一串HTML,返回一以 @@ 分割的字符串,使用split分割字符串进数组中,然后将数组的元素转列. 开始的写法 SELECT id, legal_person ...

  7. Django之ModelForm详解

    前言 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来.先来一个简单的例子来看一下这个东西怎么用: 比如我们的数据库中有这样一张学生表,字段有姓名,年龄,爱 ...

  8. Merge k Sorted Lists, k路归并

    import java.util.Arrays; import java.util.List; import java.util.PriorityQueue; /* class ListNode { ...

  9. yii2:属性

    yii2:属性 在 PHP 中,类的成员变量也被称为属性(properties). 以Foo.php类文件为例: 继承yii\base\Object类(基于类内的 getter 和 setter(读取 ...

  10. java中int i 会出现i+1i吗

    Java中int是32,范围是-2147483648到2147483647 所以i+1 < i 或者 i-1 > i是会出现的. int i=(int) Math.pow(2, 32); ...