我们先思考几个问题:
1.为什么在foreach中不能修改item的值?(IEnumerator的Current为只读)
2.要实现foreach需要满足什么条件?(实现IEnumerator接口来实现的)
3.为什么Linq to Object中要返回IEnumerable?(因为IEnumerable是延迟加载的,每次访问的时候才取值。也就是我们在Lambda里面写的where、select并没有循环遍历(只是在组装条件),只有在ToList或foreache的时候才真正去集合取值了。这样大大提高了性能。)

.net中迭代器是通过IEnumerable和IEnumerator接口来实现的,今天我们也来依葫芦画瓢。

using System;
using System.Collections; namespace RedisTest
{
class Program
{
static void Main(string[] args)
{
string[] str = { "", "", "", "", "" };
var aaa = new MyIEnumerable(str);
var bbb = aaa.GetEnumerator();
while (bbb.MoveNext())
{
Console.WriteLine(bbb.Current);
}
Console.WriteLine("---------------------------------------------------------");
foreach (var item in aaa)
{
Console.WriteLine(item);
}
Console.Read();
/*
1111
2222
3333
4444
5555
---------------------------------------------------------
1111
2222
3333
4444
5555
*/
}
} public class MyIEnumerable : IEnumerable
{
private string[] strList;
public MyIEnumerable(string[] _strList)
{
strList = _strList;
}
public IEnumerator GetEnumerator()
{
return new MyIEnumerator(strList);
}
} public class MyIEnumerator : IEnumerator
{
private string[] strList;
private int position; public MyIEnumerator(string[] _strList)
{
strList = _strList;
position = -;
}
public object Current
{
get
{
return strList[position];
}
} public bool MoveNext()
{
position++;
if (position < strList.Length)
return true;
return false;
} public void Reset()
{
position = -;
}
}
}

yield的使用

using System;
using System.Collections; namespace RedisTest
{
class Program
{
static void Main(string[] args)
{
string[] str = { "", "", "", "", "" };
var aaa = new MyIEnumerable(str);
var bbb = aaa.GetEnumerator();
while (bbb.MoveNext())
{
Console.WriteLine(bbb.Current);
}
Console.WriteLine("---------------------------------------------------------");
foreach (var item in aaa)
{
Console.WriteLine(item);
}
Console.Read();
/*
1111
2222
3333
4444
5555
---------------------------------------------------------
1111
2222
3333
4444
5555
*/ }
} public class MyIEnumerable
{
private string[] strList;
public MyIEnumerable(string[] _strList)
{
strList = _strList;
}
public IEnumerator GetEnumerator()
{
for (int i = ; i < strList.Length; i++)
{
yield return strList[i];
}
}
} }

我们调用GetEnumerator的时候,看似里面for循环了一次,其实这个时候没有做任何操作。只有调用MoveNext的时候才会对应调用for循环:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq; namespace RedisTest
{
class Program
{
static void Main(string[] args)
{
string[] str = { "", "", "", "", "" };
var aaa = new MyIEnumerable(str);
var bbb = aaa.MyWhere(x => x != "");
var ccc = bbb.ToList();
//现在看到了吧。执行到MyWhere的时候什么动作都没有(返回的就是IEnumerable),只有执行到ToList的时候才代码才真正的去遍历筛选。
//这里的MyWhere其实可以用扩展方法来实现,提升逼格。(Linq的那些查询操作符就是以扩展的形式实现的)
Console.Read(); }
} public class MyIEnumerable
{
private string[] strList;
public MyIEnumerable(string[] _strList)
{
strList = _strList;
}
public IEnumerator GetEnumerator()
{
for (int i = ; i < strList.Length; i++)
{
yield return strList[i];
}
}
public IEnumerable<string> MyWhere(Func<string, bool> func)
{
foreach (string item in this)
{
if (func(item))
{
yield return item;
}
}
}
} }

IEnumerable和IEnumerator接口的更多相关文章

  1. 细说 C# 中的 IEnumerable和IEnumerator接口

    我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...

  2. C# IEnumerable 和 IEnumerator接口浅析

    温故而知新,可以为师矣,有空经常复习一下基础知识是有必要的,并且能加深理解和记忆. Foreach常用于循环访问集合,对实现IEnumerable的接口的容器进行遍历,IEnumerable和IEnu ...

  3. IEnumerable、IEnumerator接口(如何增加迭代器功能)

    IEnumerable.IEnumerator接口封装了迭代器功能,有了它,我们不需要将内部集合暴露出去,外界只需要访问我的迭代器接口方法即可遍历数据. 在C#中,使用foreach语句来遍历集合.f ...

  4. 迭代器学习之一:使用IEnumerable和IEnumerator接口

    写博客是检验我学习的成果之一以及自我总结的一种方式,以后会经常利用这种方式进行技术交流和自我总结,其中认识不深难免会有错误,但是一直懂得不懂就问,不懂就学的道理! 1.首先看一个简单的列子 , , , ...

  5. C#基础知识系列九(对IEnumerable和IEnumerator接口的糊涂认识)

    前言 IEnumerable.IEnumerator到现在为止对这两个接口还是不太理解,不理解但是自己总是想着试着要搞明白,毕竟自己用的少,所以在此先记录一下.以备自己日后可以来翻查,同时也希望园子里 ...

  6. C# ~ 从 IEnumerable / IEnumerator 到 IEnumerable<T> / IEnumerator<T> 到 yield

    IEnumerable / IEnumerator 首先,IEnumerable / IEnumerator 接口定义如下: public interface IEnumerable /// 可枚举接 ...

  7. IEnumerable和IEnumerator

    概述 IEnumerable和IEnumerator接口存在的意义:用来实现迭代的功能! public interface IEnumerable { IEnumerator GetEnumerato ...

  8. IEnumerable和IEnumerator 详解 (转)

    原文链接:http://blog.csdn.net/byondocean/article/details/6871881 参考链接:http://www.cnblogs.com/hsapphire/a ...

  9. [转]那些年我还不懂:IList,ICollection,IEnumerable,IEnumerator,IQueryable

    1.首先看一个简单的例子 int[] myArray = { 1, 32, 43, 343 }; IEnumerator myie = myArray.GetEnumerator(); myie.Re ...

随机推荐

  1. HDU - 4324 Triangle LOVE(拓扑排序)

    https://vjudge.net/problem/HDU-4324 题意 每组数据一个n表示n个人,接下n*n的矩阵表示这些人之间的关系,输入一定满足若A不喜欢B则B一定喜欢A,且不会出现A和B相 ...

  2. 流媒体技术学习笔记之(二)RTMP和HLS分发服务器nginx.conmf配置文件(解决了,只能播放RTMP流而不能够播放HLS流的原因)

    user www www; worker_processes ; error_log logs/error.log debug; #pid logs/nginx.pid; events { worke ...

  3. memcache的下载与安装

    memcache的安装: 建议安装1.4.4版本 Windows 下安装 Memcached 官网上并未提供 Memcached 的 Windows 平台安装包,我们可以使用以下链接来下载,你需要根据 ...

  4. 007、Docker 架构详解(2018-12-24 周一)

    参考https://www.cnblogs.com/CloudMan6/p/6763789.html     Docker核心组件包括:       Docker 客户端   Docker Clien ...

  5. .NET面试题系列(十五)yong

    Redis为什么使用单进程单线程方式也这么快 Redis遍历所有key的两个命令 -- KEYS 和 SCAN 一致性Hash算法 利用一致性哈希水平拆分MySql单表 单例模式  锁 双重锁 单例模 ...

  6. android 生成、pull解析xml文件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...

  7. 数据库 之 E-R设计感想

    1.实体与实体之间的关系,在许多情况下,可以将其实体化为实体(弱实体),例如:员工租赁宿舍,可以将租赁弱实体化为实体(具有唯一主键ID) 2.一些具有特征的关系可以(弱)实体化为实体 3.实体里面可以 ...

  8. CentOS6.8配置SonarQube Scanner配合SonarQube使用

    下载最新的SonarQube Scanner压缩包  https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner ...

  9. tidb 架构 ~Tidb学习系列(4)

    一 简介:今天我们继续学习tidb 二 集群管理 0 集群配置       验证 4台一组 3个kv 一个pd+server       上线 6台一组   1 动态添加kv服务       nohu ...

  10. yum和rpm的区别

    rpm是由红帽公司开发的软件包管理方式,使用rpm我们可以方便的进行软件的安装.查询.卸载.升级等工作.但是rpm软件包之间的依赖性问题往往会很繁琐,尤其是软件由多个rpm包组成时.Yum(全称为 Y ...