首页 > 代码库 > IEnumerable和IEnumerator接口
IEnumerable和IEnumerator接口
我们先思考几个问题:
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 = { "1111", "2222", "3333", "4444", "5555" }; 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 = -1; } public object Current { get { return strList[position]; } } public bool MoveNext() { position++; if (position < strList.Length) return true; return false; } public void Reset() { position = -1; } }}
yield的使用
using System;using System.Collections;namespace RedisTest{ class Program { static void Main(string[] args) { string[] str = { "1111", "2222", "3333", "4444", "5555" }; 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 = 0; 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 = { "1111", "2222", "3333", "4444", "5555" }; var aaa = new MyIEnumerable(str); var bbb = aaa.MyWhere(x => x != "1111"); 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 = 0; 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接口
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。