一般使用方法
yield 关键字向编译器指示它所在的方法是迭代器块
在迭代器块中,yield 关键字与 return 关键字结合使用,向枚举器对象提供值。 这是一个返回值,例如,在
foreach 语句的每一次循环中返回的值。 yield 关键字也可与 break 结合使用,表示迭代结束。
不允许不安全块。
方法、运算符或访问器的参数不能是 ref 或 out。
yield return 语句不能放在 try-catch 块中的任何位置。 该语句可放在后跟 finally 块的 try 块中。
yield break 语句可放在 try 块或 catch 块中,但不能放在 finally 块中。
yield 语句不能出现在匿名方法中
Yield的执行方法
调用函数
调用者请求item
下一个item返回
回到步骤2
yield不能单独放在try-catch块中,如果try中有yield那么,这个try块后面不许跟着finally块;也不能出现在匿名
方法中,所以,看起来yield似乎并不常用,但是也不是不用。我前面有一个关于迭代器的例子《C#中的迭代器基础
》中就用到了。可以参考一下那个例子,但是这里要再说的一点是我后来看到的,yield是跟return一起使用的,形
式为yield return xxx,一般来说单独的return在每个方法中只能存在一个。而yield则不同的是,可以出现连续多
个。
迭代器,是一个连续的集合,出现多个yield return其实就是将这多个的yield return元素按照出现的顺序存储在迭
代器的集合中而已
static IEnumerable<Int32> CountWithTimeLimit(DateTime limit)
{
try
{
for (int i = 1; i <= 100; i++)
{
if (DateTime.Now >= limit)
{
yield break;
}
yield return i;
}
}
finally
{
Console.WriteLine("停止迭代!"); Console.ReadKey();
}
}
static void Main(string[] args)
{
DateTime stop = DateTime.Now.AddSeconds(2);
foreach (Int32 i in CountWithTimeLimit(stop))
{
Console.WriteLine("返回 {0}", i);
Thread.Sleep(300);
}
}
简单几行代码就能够完全实现IterationSampleIterator类所需要的功能。方法看起来很普通,除了使用了yield
return。这条语句告诉编译器这不是一个普通的方法,而是一个需要执行的迭代块(yield block),他返回一个
IEnumerator对象,你能够使用迭代块来执行迭代方法并返回一个IEnumerable需要实现的类型,IEnumerator或者对
应的泛型。如果实现的是非泛型版本的接口,迭代块返的yield type是Object类型,否则返回的是相应的泛型类型。
例如,如果方法实现IEnumerable<String>接口,那么yield返回的类型就是String类型。 在迭代块中除了yield
return外,不允许出现普通的return语句。块中的所有yield return 语句必须返回和块的最后返回类型兼容的类型
。举个例子,如果方法定义需要返回IEnumeratble<String>类型的话,不能yield return 1 。 需要强调的一点是,
对于迭代块,虽然我们写的方法看起来像是在顺序执行,实际上我们是让编译器来为我们创建了一个状态机。这就是
在C#1中我们书写的那部分代码---调用者每次调用只需要返回一个值,因此我们需要记住最后一次返回值时,在集合
中位置。 当编译器遇到迭代块是,它创建了一个实现了状态机的内部类。这个类记住了我们迭代器的准确当前位置
以及本地变量,包括参数。这个类有点类似与我们之前手写的那段代码,他将所有需要记录的状态保存为实例变量。
下面来看看,为了实现一个迭代器,这个状态机需要按顺序执行的操作:
它需要一些初始的状态
当MoveNext被调用时,他需要执行GetEnumerator方法中的代码来准备下一个待返回的数据。
当调用Current属性是,需要返回yielded的值。
需要知道什么时候迭代结束是,MoveNext会返回false
class Program
{
static readonly String Padding = new String(' ', 30);
static IEnumerable<Int32> CreateEnumerable()
{
Console.WriteLine("{0} CreateEnumerable()方法开始", Padding);
for (int i = 0; i < 3; i++)
{
Console.WriteLine("{0}开始 yield {1}", i);
yield return i;
Console.WriteLine("{0}yield 结束", Padding);
}
Console.WriteLine("{0} Yielding最后一个值", Padding);
yield return -1;
Console.WriteLine("{0} CreateEnumerable()方法结束", Padding);
}
static void Main(string[] args)
{
IEnumerable<Int32> iterable = CreateEnumerable();
IEnumerator<Int32> iterator = iterable.GetEnumerator();
Console.WriteLine("开始迭代");
while (true)
{
Console.WriteLine("调用MoveNext方法……");
Boolean result = iterator.MoveNext();
Console.WriteLine("MoveNext方法返回的{0}", result);
if (!result)
{
break;
}
Console.WriteLine("获取当前值……");
Console.WriteLine("获取到的当前值为{0}", iterator.Current);
}
Console.ReadKey();
}
}
------------------------------------------------------------------------------------------
public class List
{
//using System.Collections;
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
- C#使用yield关键字构建迭代器
http://www.cnblogs.com/Huaran1chendu/p/4838536.html 以前,如果我们希望构建支持foreach枚举的自定义集合,只能实现IEnumerable接口(可 ...
- Python:容器、迭代对象、迭代器、生成器及yield关键字
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...
- 使用yield关键字让自定义集合实现foreach遍历
一般来说当我们创建自定义集合的时候为了让其能支持foreach遍历,就只能让其实现IEnumerable接口(可能还要实现IEnumerator接口) 但是我们也可以通过使用yield关键字构建的迭代 ...
- (转) Python Generators(生成器)——yield关键字
http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...
- 转载yield关键字理解
实现IEnumerable接口及理解yield关键字 [摘要]本文介绍实现IEnumerable接口及理解yield关键字,并讨论IEnumerable接口如何使得foreach语句可以使用. 本 ...
- C# 基础小知识之yield 关键字 语法糖
原文地址:http://www.cnblogs.com/santian/p/4389675.html 对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味 ...
- C#2.0中使用yield关键字简化枚举器的实现
我们知道要使用foreach语句从客户端代码中调用迭代器,必需实现IEnumerable接口来公开枚举器,IEnumerable是用来公开枚举器的,它并不实现枚举器,要实现枚举器必需实现IEnumer ...
- yield关键字
1.yield语句有两种形式 (1)yield return <expression>;一次返回一个元素 运行yield return 语句时,会返回一个 值,并记录当前位置及保留该值.下 ...
- python yield 关键字
最近看代码看到python里面的yield关键字,和我之前接触的语言好像都没有来着,我就查了查它的含义,大概理解如下: >>> def createGenerator(): ... ...
随机推荐
- 关于SQL\SQL Server的三值逻辑简析
在SQL刚入门的时候,我们筛选为某列值为NULL的行,一般会采用如下的方式: SELECT * FROM Table AS T WHERE T.Col=NULL www.2cto.com 而实际 ...
- Strom的安装及使用
在使用storm之前,首先看zookeeper是否安装好 单机版 1.在node1上修改配置文件conf下的storm.yaml文件
- 2015年10月22日CSS学习笔记
XHTML1.0对HTML4.0的改进 借鉴了XML的写法,语法更加严格. 把页面的内容和样式分离了,废弃了html4中的表示样式的标签和属性.推荐使用css来描述页面的样式. CSS样式的优先级 ! ...
- C#学习:集合、迭代、泛型(1)
一.System.Collections名称空间下几个接口表征着集合的功能: 1.IEnumerable:表征着迭代功能 public interface IEnumerable { IEnumera ...
- 使用Cross-validation (CV) 调整Extreme learning Machine (ELM) 最优参数的实现(matlab)
ELM算法模型是最近几年得到广泛重视的模型,它不同于现在广为火热的DNN. ELM使用传统的三层神经网络,只包含一个隐含层,但又不同于传统的神经网络.ELM是一种简单易用.有效的单隐层前馈神经网络SL ...
- HW4.43
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- Microsoft Dynamics CRM 2011 面向Internet部署 (IFD) ADFS虚拟机环境搭建的步骤(CRM与ADFS装在同一台服务器上) 摘自网络
1: 安装windows server 2008 R2 中文版 (过程略) 安装完成后设置机器名和IP地址, 本过程机器名 crm5dev,192.168.0.110 dns: 192.168.0.1 ...
- 2015 CCPC-C-The Battle of Chibi (UESTC 1217)(动态规划+树状数组)
赛后当天学长就说了树状数组,结果在一个星期后赖床时才有了一点点思路…… 因为无法提交,不确定是否正确..嗯..有错希望指出,谢谢... 嗯..已经A了..提交地址http://acm.uestc.ed ...
- Java和.NET的GZIP压缩功能对比
本文主要比较了Java和.NET提供的GZIP压缩功能. 介绍 在本文中,我们将讨论Java和.NET提供的GZIP压缩功能,并且用实例来说明哪个压缩方法更佳. 在Java中,我们有提供GZIP压缩的 ...
- Tuple元组
Tuple元组 Tuple 是 Storm 的主要数据结构,并且是 Storm 中使用的最基本单元.数据模型和元组. Tuple 描述 Tuple 就是一个值列表, Tuple 中的值可以是任何类型的 ...