一、几个基本概念的理解

问题一:为什么数组可以使用foreach输出各元素

答:数组是可枚举类型,它实现了一个枚举器(enumerator)对象;枚举器知道各元素的次序并跟踪它们的位置,然后返回请求的当前项

问题二:不用foreach能不能遍历各元素

问题三:什么是可枚举类

答:可枚举类是指实现了IEnumerable接口的类;IEnumerable接口只有一个成员GetEnumerator方法,它返回对象的枚举器

问题四:什么是枚举器

答:实现了IEnumerator接口的枚举器包含三个函数成员:Current,MoveNext,Reset

Current是只读属性,它返回object类型的引用;

MoveNext是把枚举器位置前进到集合的下一项的方法,它返回布尔值,指示新的位置是否有效位置还是已经超过了序列的尾部;

Reset是把位置重置为原始状态的方法;

二、下面代码展示了一个可枚举类的完整示例

  1 namespace ConsoleApplication4
2 {
3 /// <summary>
4 /// 自定义一个枚举对象
5 /// </summary>
6 class ColorEnumerator : IEnumerator
7 {
8 private string[] _colors;
9 private int _position = -1;
10
11 public ColorEnumerator(string[] arr)
12 {
13 _colors = arr;
14 for (int i = 0; i < arr.Length; i++)
15 {
16 _colors[i] = arr[i];
17 }
18 }
19 public object Current
20 {
21 get
22 {
23 if (_position == -1)
24 {
25 throw new InvalidOperationException();
26 }
27 if (_position >= _colors.Length)
28 {
29 throw new InvalidOperationException();
30 }
31 return _colors[_position];
32 }
33 }
34
35 public bool MoveNext()
36 {
37 if (_position < _colors.Length - 1)
38 {
39 _position++;
40 return true;
41 }
42 else
43 {
44 return false;
45 }
46 }
47
48 public void Reset()
49 {
50 _position = -1;
51 }
52 }
53
54 /// <summary>
55 /// 创建一个实现IEnumerable接口的枚举类
56 /// </summary>
57 class Spectrum : IEnumerable
58 {
59 private string[] Colors = { "red", "yellow", "blue" };
60 public IEnumerator GetEnumerator()
61 {
62 return new ColorEnumerator(Colors);
63 }
64 }
65
66 class Program
67 {
68 static void Main(string[] args)
69 {
70 Spectrum spectrum = new Spectrum();
71 foreach (string color in spectrum)
72 {
73 Console.WriteLine(color);
74 }
75 Console.ReadKey();
76 }
77 }
78 }
79

三、泛型枚举接口

IEnumerable<T>接口的GetEnumerator方法返回实现IEnumerator<T>的枚举类的实例;

实现IEnumerator<T>的类实现了Current属性,它返回实际类型的对象,而不是object基类的引用;

所以非泛型接口的实现不是类型安全的,因为还需要转换为实际类型。

四、迭代器

1.使用迭代器来创建枚举器

  1 namespace ConsoleApplication5
2 {
3 class MyClass
4 {
5 /// <summary>
6 /// 获取一个迭代器
7 /// </summary>
8 /// <returns></returns>
9 public IEnumerator<string> GetEnumerator()
10 {
11 return ColorEnumerator();
12 }
13 /// <summary>
14 /// 迭代器
15 /// </summary>
16 /// <returns></returns>
17 public IEnumerator<string> ColorEnumerator()
18 {
19 yield return "red";
20 yield return "yellow";
21 yield return "blue";
22 }
23 }
24 class Program
25 {
26 static void Main(string[] args)
27 {
28 MyClass mc = new MyClass();
29 foreach (string color in mc)
30 {
31 Console.WriteLine(color);
32 }
33 Console.ReadKey();
34 }
35 }
36 }

2.使用迭代器来创建枚举类型

  1 namespace ConsoleApplication6
2 {
3 class MyClass
4 {
5 public IEnumerator<string> GetEnumerator()
6 {
7 //获取可枚举类型
8 IEnumerable<string> enumerable = ColorEnumerable();
9 //获取枚举器
10 return ColorEnumerable().GetEnumerator();
11 }
12
13 public IEnumerable<string> ColorEnumerable()
14 {
15 yield return "red";
16 yield return "yellow";
17 yield return "blue";
18 }
19 }
20 class Program
21 {
22 static void Main(string[] args)
23 {
24 MyClass mc = new MyClass();
25 //使用类对象
26 foreach (string color in mc)
27 {
28 Console.WriteLine(color);
29 }
30 Console.WriteLine("-----------------------");
31 //使用类枚举器的方法
32 foreach (string color in mc.ColorEnumerable())
33 {
34 Console.WriteLine(color);
35 }
36 Console.ReadKey();
37 }
38 }
39 }

3.产生多个可迭代类型

  1 namespace ConsoleApplication7
2 {
3 class MyClass
4 {
5 private string[] Colors = { "red", "yellow", "blue" };
6 //顺序
7 public IEnumerable<string> ColorOrder()
8 {
9 for (int i = 0; i < Colors.Length; i++)
10 {
11 yield return Colors[i];
12 }
13 }
14 //逆序
15 public IEnumerable<string> ColorReversed()
16 {
17 for (int i = Colors.Length - 1; i >= 0; i--)
18 {
19 yield return Colors[i];
20 }
21 }
22 }
23 class Program
24 {
25 static void Main(string[] args)
26 {
27 MyClass mc = new MyClass();
28 foreach (string color in mc.ColorOrder())
29 {
30 Console.WriteLine(color);
31 }
32 Console.WriteLine("------------------");
33 foreach (string color in mc.ColorReversed())
34 {
35 Console.WriteLine(color);
36 }
37 Console.ReadKey();
38 }
39 }
40 }
41

C#知识点-枚举器和迭代器的更多相关文章

  1. C#图解教程 第十八章 枚举器和迭代器

    枚举器和迭代器 枚举器和可枚举类型 foreach语句 IEnumerator接口 使用IEnumerable和IEnumerator的示例 泛型枚举接口迭代器 迭代器块使用迭代器来创建枚举器使用迭代 ...

  2. C# 枚举器和迭代器

    一.枚举器(enumerator)和可枚举类型(enumeration) 我们都知道foreach语句可以用来遍历数组中的元素,但你有没有想过为什么它可以被foreach处理呢? 这是因为数组可以按需 ...

  3. 设计模式 - 适配器模式(adapter pattern) 枚举器和迭代器 具体解释

    适配器模式(adapter pattern) 枚举器和迭代器 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考适配器模式(adapter patter ...

  4. C#-14 枚举器和迭代器

    一 枚举器和可枚举类型 当我们为数组使用foreach语句时,这个语句为我们依次取出了数组中的每一个元素. var arrInt = new int[] { 11, 12, 13, 14 }; for ...

  5. 【Unity|C#】基础篇(20)——枚举器与迭代器(IEnumerable/IEnumerator)

    [学习资料] <C#图解教程>(第18章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...

  6. C#枚举器/迭代器

    一.枚举器 1.为什么foreach可以顺序遍历数组? 因为foreach可以识别可枚举类型,通过访问数组提供的枚举器对象来识别数组中元素的位置从而获取元素的值并打印出来. 2.什么是枚举器?可枚举类 ...

  7. C#中的枚举器(转)

    术语表 Iterator:枚举器(迭代器) 如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.这在C# 2.0中比 C# 1.1更容 ...

  8. ruby迭代器枚举器

    迭代器一个迭代器是一个方法,这个方法里面有yield语句,使用了yield的方法叫做迭代器,迭代器并非一定要迭代,与传递给这个方法的块进行数据传输 yield将数据传给代码快,代码块再把数据传输给yi ...

  9. ruby中迭代器枚举器的理解

    参考<ruby编程语言>5.3迭代器和可枚举对象 迭代器一个迭代器是一个方法,这个方法里面有yield语句,这个方法里的yield语句,与传递给这个方法的块进行数据传输 yield将数据传 ...

随机推荐

  1. Just a Hook-HDU1698(线段树求区间)

    http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem Description In the game of DotA, Pudge’s meat ...

  2. 记一次springMVC的跨域解决方案

    日期:2019年5月18日 事情原因:由于微信小程序的开发只有测试环境,而后台提供借口的环境是开发环境:两个环境的域名不同,导致前端开发产生了跨域问题: 理论概念: 1.同源策略:同源策略是浏览器的安 ...

  3. 一步步搭建java信息管理系统00 - 前言

    开发前,先上效果图吧 信息管理系统,个人认为,以下几个因素是不可缺少的 多tab 因菜单比较多,右侧的树形一定要考虑,如果菜单还是多,那么顶部就要考虑起来了 以后想到什么,再添加吧. 看到easyui ...

  4. node-load module

    javscript :脚本建共享全局名称空间(全局污染). node:实现CommonJS(公共)模块标准. Node加载模块,有两种方式: 1.通过名称 除非是核心模块,否则被引用的模块最后都会映射 ...

  5. ajax请求同步与异步的区别

    //同步请求 $.ajax({    type:'post', url:"<c:url value='/device/org/' />"+val, data:{'org ...

  6. 省市县三级联动js代码

    省市县三级联动菜单,JS全国省市县(区)联动代码,一般可以用于用户注册或分类信息二手交易网站,需要的朋友直接复制代码就可以用了,不过有朋友反馈说缺少某些城市,具体缺少哪个尚不知,请想用的朋友自己补全吧 ...

  7. 分布式数据库DDM Sidecar模式负载均衡

    简介 1.分布式数据库中间件 DDM 分布式数据库中间件(Distributed Database Middleware)是解决数据库容量.性能瓶颈和分布式扩展问题的中间件服务,提供分库分表.读写分离 ...

  8. iOS CMSampleBuffer deep copy

    extension CVPixelBuffer { func copy() -> CVPixelBuffer { precondition(CFGetTypeID(self) == CVPixe ...

  9. jeasyui控件事件和方法的使用方法

    1.事件是在页面加载后就注册绑定: $(function () { ocr(); }); function ocr() { $('#dgTeacher').datagrid({ onClickRow: ...

  10. 【bzoj1406】[AHOI2007]密码箱

    x2 ≡ 1 mod n => x2 = k * n + 1 => n | (x + 1) * (x - 1) 令n = a * b,则 (a | x + 1 且 b | x - 1) 或 ...