我们先思考几个问题:
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;
}
}
}
} }

最新文章

  1. JQM开发Tips
  2. ASP.NET MVC5--添加验证
  3. zepto--toggle函数
  4. java面试笔试试题http://www.jobui.com/mianshiti/it/java/6827/
  5. 浅谈sqlserver数据库优化(一)----开光篇
  6. 快速学习bootstrap前台框架
  7. SDPLR的安装过程(matlab)
  8. Creating a simple static file server with Rewrite--reference
  9. 通过Web Deploy方式部署WCF
  10. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
  11. 一个web应用的诞生(1)--初识flask
  12. H5 EventSource 实现web页面推送功能demo
  13. 软件测试assert
  14. Kaggle-房价预测
  15. Go语言文件操作
  16. Python+Selenium 自动化实现实例-处理分页(pagination)
  17. WebLogic Server添加删除补丁操作【转】【补】
  18. Java——ikanalyzer分词&#183;只用自定义词库
  19. Git -- 相关命令
  20. 【代码审计】TuziCMS_v3.0_任意文件删除漏洞分析

热门文章

  1. bzoj千题计划302:bzoj3160: 万径人踪灭
  2. bzoj千题计划297:bzoj3629: [JLOI2014]聪明的燕姿
  3. 正方体旋转demo
  4. 致敬Python 2.7! 致敬unicode函数!
  5. 四、NAND Flash
  6. asp.net mvc4 在EF新增的时候报对一个实体或多个实体验证失败
  7. C# 使用ffmpeg视频截图
  8. python时间序列画图plot总结
  9. Poj3696 The Lukiest Number
  10. transform,变换