转载yield关键字理解
实现IEnumerable接口及理解yield关键字
[摘要]本文介绍实现IEnumerable接口及理解yield关键字,并讨论IEnumerable接口如何使得foreach语句可以使用。
本文讨论题目的内容。然后讨论IEnumerable接口如何使得foreach语句可以使用。之后会展示如果实现自定义的集合类,该集合类实现了IEnumerable接口。Yield关键字和遍历集合后面也讨论。
背景
一使用集合。就发现遍历集合就跟着来了。遍历集合最好的方式是实现迭代器模式-Understanding and Implementing the Iterator Pattern in C# and C++ ,C#提供foreach来以一种优雅的方式遍历。
只要集合实现了IEnumerable 接口就可以用foreach来遍历。
使用代码
首先先看一下内置的集合类如何使用foreach来遍历的。ArrayList实现了IEnumerable 接口。我们看一下:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
// 看一下实现了IEnumerable 接口的集合如何遍历 ArrayList list = new ArrayList(); list.Add("1"); list.Add(2); list.Add("3"); list.Add('4'); foreach (object s in list) { Console.WriteLine(s); } |
遍历泛型集合类
Arraylist 是一个通用集合类,遍历泛型集合类也可以。因为这些泛型集合类实现了IEnumerable<T>接口,看一下吧。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
// 遍历实现了IEnumerable<T>接口的泛型类 List<string> listOfStrings = new List<string>(); listOfStrings.Add("one"); listOfStrings.Add("two"); listOfStrings.Add("three"); listOfStrings.Add("four"); foreach (string s in listOfStrings) { Console.WriteLine(s); } |
发现了吧。我们自定义的集合类或是泛型集合类应该实现IEnumerable和IEnumerable<T>接口。这样就可以遍历了。
理解yield关键字
在写个实现接口的例子之前,先理解一下yield关键字,yield会记录集合位置。当从一个函数返回一个值的时候,yield可以用。
如下的普通的方法。不论调用多少次,都只会返回一个return。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static int SimpleReturn() { return 1; return 2; return 3; } static void Main(string[] args) { // 看看 Console.WriteLine(SimpleReturn()); Console.WriteLine(SimpleReturn()); Console.WriteLine(SimpleReturn()); Console.WriteLine(SimpleReturn()); } |
原因就是普通的return语句不保留函数的返回状态。每一次都是新的调用。然后返回第一个值。
但是使用下面的语句替换后就不一样。当函数第二次调用的时候。会从上次返回的地方继续调用:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static IEnumerable<int> YieldReturn() { yield return 1; yield return 2; yield return 3; } static void Main(string[] args) { // 看看yield return的效果 foreach (int i in YieldReturn()) { Console.WriteLine(i); } } |
显然返回1,2,3,唯一要注意的就是函数需要返回IEnumerable。,然后通过foreach调用。
在自定义的集合类里实现Ienumerable接口
现在如果我们在我们的自定义集合里定义一个方法。来迭代所有元素。然后通过使用yield返回。我们就可以成功了。
好。我们定义MyArrayList 类,实现IEnumerable 接口,该接口就会强制我们实现GetEnumerator 函数。这里我们就要使用yield了。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
class MyArrayList : IEnumerable { object[] m_Items = null; int freeIndex = 0; public MyArrayList() { // 对了方便我直接用数组了,其实应该用链表 m_Items = new object[100]; } public void Add(object item) { // 考虑添加元素的时候 m_Items[freeIndex] = item; freeIndex++; } // IEnumerable 函数 public IEnumerator GetEnumerator() { foreach (object o in m_Items) { // 检查是否到了末尾。数组的话。。。没写好 if(o == null) { break; } // 返回当前元素。然后前进一步 yield return o; } } } |
之后你就可以用foreach遍历了。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static void Main(string[] args) { //看看调用部分 MyArrayList myList = new MyArrayList(); myList.Add("1"); myList.Add(2); myList.Add("3"); myList.Add('4'); foreach (object s in myList) { Console.WriteLine(s); } } |
这个类啊。没写好。也不完整。只要是让你理解。。模拟一下而已。
自定义泛型类里实现Ienumerable<T>接口
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
class MyList<T> : IEnumerable<T> { T[] m_Items = null; int freeIndex = 0; public MyList() { // 为了方便。使用数组 m_Items = new T[100]; } public void Add(T item) { //添加元素 m_Items[freeIndex] = item; freeIndex++; } #region IEnumerable<T> Members public IEnumerator<T> GetEnumerator() { foreach (T t in m_Items) { //检查是否到了末尾。数组的话。。。没写好 if (t == null) // 如果T不是一个可空类型。就中断 { break; } // 返回当前元素,然后前进一步 yield return t; } } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { // 此处调用泛型版本 return this.GetEnumerator(); } #endregion } |
之后就可以使用foreach了。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
static void Main(string[] args) { // 使用示例 MyList<string> myListOfStrings = new MyList<string>(); myListOfStrings.Add("one"); myListOfStrings.Add("two"); myListOfStrings.Add("three"); myListOfStrings.Add("four"); foreach (string s in myListOfStrings) { Console.WriteLine(s); } } |
转载yield关键字理解的更多相关文章
- C#中yield关键字理解
yield关键字之前用得较少,但是在做项目开发的过程中也遇到了,当时有点迷惑,就顺便研究学习了一下,以下是个人理解,不到之处欢迎拍砖!废话就到这,上代码: class Program { static ...
- [原译]实现IEnumerable接口&理解yield关键字
原文:[原译]实现IEnumerable接口&理解yield关键字 著作权声明:本文由http://leaver.me 翻译,欢迎转载分享.请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢 ...
- 深入理解python中的yield关键字
想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...
- 理解 ES6 语法中 yield 关键字的返回值
在 ES6 中新增了生成器函数的语法,本文解释了生成器函数内 yield 关键字的返回值. 描述 根据语法规范,yield 关键字用来暂停和继续执行一个生成器函数.当外部调用生成器的 next() 方 ...
- 理解 ES6 语法中 yield* 关键字的作用
在 ES6 中新增了生成器函数的语法,本文解释了与生成器函数有关的 yield* 关键字,及其使用场景. 描述 根据语法规范,yield* 的作用是代理 yield 表达式,将需要函数本身产生(yie ...
- C# 基础小知识之yield 关键字 语法糖
原文地址:http://www.cnblogs.com/santian/p/4389675.html 对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味 ...
- C# 基础小知识之yield 关键字
对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味着它在其中出现的方法.运算符或 get 访问器是迭代器. 通过使用 yield 定义迭代器,可在实现自 ...
- 解析Python中的yield关键字
前言 python中有一个非常有用的语法叫做生成器,所利用到的关键字就是yield.有效利用生成器这个工具可以有效地节约系统资源,避免不必要的内存占用. 一段代码 def fun(): for i i ...
- python yield 关键字
最近看代码看到python里面的yield关键字,和我之前接触的语言好像都没有来着,我就查了查它的含义,大概理解如下: >>> def createGenerator(): ... ...
随机推荐
- 新浪实时股票数据接口http://hq.sinajs.cn/list=code
股票数据的获取目前有如下两种方法可以获取:1. http/javascript接口取数据2. web-service接口 1.http/javascript接口取数据1.1Sina股票数据接口以大秦铁 ...
- JdbcTemplate查询数据 三种callback之间的区别
JdbcTemplate针对数据查询提供了多个重载的模板方法,你可以根据需要选用不同的模板方法. 如果你的查询很简单,仅仅是传入相应SQL或者相关参数,然后取得一个单一的结果,那么你可以选择如下一组便 ...
- Python3 学习第一弹:基本数据类型
本人学习主要从<python基础教程第二版>,<dive into python3>等书籍,及一些网上大牛的博客中学习特别是Python官方文档<Python Tutor ...
- word编辑器解码集合
$(document).ready(function () { $(".content").each(function () { var content = $(this).htm ...
- uva12230Crossing Rivers
数学期望. 过每条河的时间的可能在[L/v,3*L/v]间均匀分布,数学期望为2*L/v. 然后在加上在陆上走的时间. #include<cstdio> #include<algor ...
- Android之 学习路线
第一阶段:Java面向对象编程 1.Java基本数据类型与表达式,分支循环. 2.String和StringBuffer的使用.正则表达式. 3.面向对象的抽象,封装,继承,多态,类与对象,对象初 ...
- PHP中 对象自动调用的方法:__set()、__get()、__tostring()
总结: (1)__get($property_name):获取私有属性$name值时,此对象会自动调用该方法,将属性name值传给参数$property_name,通过这个方法的内部 执行,返回我们传 ...
- 脚本AI与脚本引擎
Scripted AI and Scripting Engines 脚本AI与脚本引擎 This chapter discusses some of the techniques you can us ...
- apache多站点配置+多端口配置
Apache多站点配置 这种方法是配置不同的地址访问不同的文件夹的配置 1:修改本机的hosts文件,如下: 示例: 127.0.0.1 localhost 127.0.0.1 www.dede.co ...
- 【转】iOS类似Android上toast效果
原文网址:http://m.blog.csdn.net/article/details?id=50478737 做过Android开发的人都知道toast,它会在界面上显示一排黑色背景的文字,用于提示 ...