foreach语句是枚举器(enumerator)的消费者,而迭代器(iterator)是枚举器的产生者。

迭代器模式能提供一种顺序访问一个集合内部的元素,而又不会暴露其内部的方法。当然其缺点就是用foreach语句遍历的同时,不能修改集合内部的元素。

我们已经在foreach语句中接触过了它 foreach (var item in collection) ,C#利用foreach实现了访问迭代器的内置支持。

实际上foreach被编译后会产生GetEnumerator和MoveNext方法,还有current属性。

一.C#2 便捷的语法糖

下面我们先来介绍C#2.0为实现迭代器提供的便捷语法。

先看两个单词的翻译 enumerator(枚举器) enumerable(可枚举类型)

下面举个例子:

using System;
using System.Collections;
using System.Collections.Generic; namespace ConsoleApp1
{ class Program
{
static IEnumerable<string> AddAB(int Count)
{
string str = "h";
for (int i = ; i < Count; i++)
{
yield return str;
str += "a";
}
Console.WriteLine("");
for (int i = ; i < Count; i++)
{
Console.WriteLine("before yoeld return "+str);
yield return str;
str += "b";
}
}
static void Main(string[] args)
{
foreach (var str in AddAB())
{
Console.WriteLine(str);
}
}
}
}

IEnumerable接口的GetEnumerator方法实现了IEnumerator枚举器类的实例。所以上文的代码是没问题的,后面会给大家示范用IEnumertor接口实现迭代器。

yield return语句的意思是你向我请求从枚举器产生的下一个元素。

每次执行到yield return就会返回到他调用者那,但还会执行yield return之后的语句,直到碰到下一条yield return时停止。这个状态一直持续到foreach语句的结束。

二.C#1 手写迭代器

再来看看这句话:foreach语句是枚举器(enumerator)的消费者,而迭代器(iterator)是枚举器的产生者。
【enumerator(枚举器) enumerable(可枚举类型)】

foreach需要获得一个enumerator,而我们需要用IEnumerator接口实现迭代器。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq; namespace ConsoleApp1
{
class Alp : IEnumerable
{
string[] value = { "a", "b", "c" };
public IEnumerator GetEnumerator()
{
return new AlpEnumerator(value);
}
}
class AlpEnumerator : IEnumerator
{
string[] alp;
int position = -;
public AlpEnumerator(string[] str)
{
alp = new string[str.Length];
for (int i = ; i < str.Length; i++)
{
alp[i] = str[i];
}
}
public object Current
{
get
{
if (position == -)
throw new InvalidOperationException();
if (position >= alp.Length)
throw new InvalidOperationException();
return alp[position];
}
} public bool MoveNext()
{
if (position < alp.Length - )
{
position++;
return true;
}
else
return false;
} public void Reset()
{
position = -;
}
}
class Program
{ static void Main(string[] args)
{
Alp alp = new Alp();
foreach (var item in alp)
{
Console.WriteLine(item);
}
}
}
}
  • Current      获取当前位置
  • MoveNext  判断是否可移动到下一位
  • Reset         将位置重置为初始位置

C#基础--迭代器初识的更多相关文章

  1. python基础——迭代器

    python基础——迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器 ...

  2. python基础—迭代器、生成器

    python基础-迭代器.生成器 1 迭代器定义 迭代的意思是重复做一些事很多次,就像在循环中做的那样. 只要该对象可以实现__iter__方法,就可以进行迭代. 迭代对象调用__iter__方法会返 ...

  3. java基础-迭代器(Iterator)与增强for循环

    java基础-迭代器(Iterator)与增强for循环 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Iterator迭代器概述 Java中提供了很多个集合,它们在存储元素时 ...

  4. 316python 基础之计算机基础、Python简介、变量、注释、基础数据类型初识、if、while、语句

    一.计算机基础. cpu:相当于人的大脑,运算与控制中心. 速度 飞机 内存:4G,8G,16G....暂时存储,供给cpu数据. 速度 高铁.成本高,断电即消失. 硬盘:相当于你电脑的数据库,存储着 ...

  5. 081 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 06 new关键字

    081 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 06 new关键字 本文知识点:new关键字 说明:因为时间紧张,本人写博客过程中只是 ...

  6. 080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则

    080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则 本文知识点:单一职责原则 说明:因为时间紧张,本人写博客过程中只是 ...

  7. 079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象

    079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象 本文知识点:实例化对象 说明:因为时间紧张,本人写博客过程中只是对知 ...

  8. 078 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 03 创建类

    078 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 03 创建类 本文知识点:创建类 说明:因为时间紧张,本人写博客过程中只是对知识点的关 ...

  9. 077 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 02 类和对象

    077 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 02 类和对象 本文知识点:类和对象 说明:因为时间紧张,本人写博客过程中只是对知识点 ...

随机推荐

  1. Thymeleaf模板笔记

    1.常用标签: 使用thymeleaf模板,首要在html中引入: <html xmlns:th="http://www.thymeleaf.org"> 引入css.j ...

  2. Nginx笔记总结十九:nginx + fancy实现漂亮的索引目录

    编译:./configure --prefix=/usr/local/nginx --add-module=../ngx-fancyindex-master 配置: location / { fanc ...

  3. Java实现Luhm算法--银行卡号合法性校验

    银行卡是由"发卡行标识代码 + 自定义 + 校验码 "等部分组成的. 银联标准卡与以往发行的银行卡最直接的区别就是其卡号前6位数字的不同.   银行卡卡号的前6位是用来表示发卡银行 ...

  4. 18.09.22模拟赛T2 历史

    网上基本上找不到这道题,何况LJJ还稍微改了一下...... 原题:传送门 题目描述 ljj 被S 国数不清的漂亮小姐姐所吸引,为了搞清楚为什么S 国有如此多的漂亮小姐姐,他决定研究S 国的历史. 根 ...

  5. 吴裕雄--天生自然 R语言开发学习:使用ggplot2进行高级绘图(续二)

    #----------------------------------------------------------# # R in Action (2nd ed): Chapter 19 # # ...

  6. struts2和springmvc性能比较2

    我们用struts2时采用的传统的配置文件的方式,并没有使用传说中的0配置.spring3 mvc可以认为已经100%零配置了(除了配置spring mvc-servlet.xml外). Spring ...

  7. 递归遍历磁盘下的某一文件夹中所有文件,并copy文件生成文件和带文件夹的文件

    package com.hudong.test; import java.io.File; import java.io.IOException; import java.util.ArrayList ...

  8. Autotestplat.com 更新了!

    1 提供测试发帖留言功能 2 自动化平台体验功能 3 提供招聘资讯功能       4 提供推荐书籍功能

  9. usb设备枚举过程

    USB主机在检测到USB设备插入后,就要对设备进行枚举了.为什么要枚举呢?枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设 ...

  10. iOS常用框架源码分析

    SDWebImage NSCache 类似可变字典,线程安全,使用可变字典自定义实现缓存时需要考虑加锁和释放锁 在内存不足时NSCache会自动释放存储的对象,不需要手动干预 NSCache的key不 ...