若是问你最经常使用的设计模式是哪一种?你可能会说单例模式,工厂模式。但根据我在项目里的经验,一个完整的应用,应该是迭代器模式。html
在本项中将会带你们一块儿进入迭代器模式下的IL代码,看看迭代器内部是怎么去进行循环迭代的;
以下代码实现了for循环打印集合中的全部元素,以及foreach迭代打印集合中的全部元素。算法
static void Main(string[] args) { List<int> intList = new List<int>(); intList.Add(1); intList.Add(2); for(var i=0;i<intList.Count;i++) { Console.WriteLine("元素for遍历打印:" + intList[i]); } foreach (var item in intList) { Console.WriteLine("元素foreach遍历打印:" + item); } }
代码输出:
设计模式
能够看到两种打印方式效果一致;for循环任一一种语言都有,你们再熟悉不过,这里再也不赘述,咱们来看下foreach迭代器模式的IL代码(若是当前网页过小,看不清,请将图片右键另存打开,或者将图片拖到浏览器新窗口打开);
数组
大概思路以下:List 下有个迭代器Enumerator,能够经过List下的GetEnumerator方法得到此迭代器集合;而后经过迭代器的get_Current方法来获取当前第一个元素。迭代器的MoveNext()方法判断下一元素是否存在,若是存在取出循环;不存在结束迭代循环模式;最终,将迭代过程当中产生的系统非托管资源释放;浏览器
迭代器代码以下:设计
var enumerator = intList.GetEnumerator(); while (enumerator.MoveNext()) { Console.WriteLine("迭代器模式遍历打印:" + enumerator.Current); } Console.ReadLine();
List<int> intList = new List<int>(); intList.Add(1); intList.Add(2); for(var i=0;i<intList.Count;i++) { if (intList[i] == 1) { intList.Remove(1); } } Console.WriteLine("集合中元素数量:" + intList.Count);
Console输出
集合中元素数量:1
这说明for删除成功code
foreach (var item in intList) { if (item==1) { intList.Remove(1); } } Console.WriteLine("集合中元素数量:" + intList.Count);
从如上抛出的异常得得知 var enumerator = intList.GetEnumerator();迭代器在循环迭代中是不容许对该迭代器进行删除操做的。若是须要删除操做,能够再这个集合基础上作linq操做;由于迭代器在循环迭代中是一个值对象的存在,不容许变动迭代器对象的内容;htm
思考对象
以下代码也是运用了迭代器模式,为何能删除集合元素了?读者自行思考哈。这也是迭代器方式下牺牲内存来删除/修改元素的一种方法。blog
foreach (var item in dictionary.ToList()) { Debug.Log(item.Key + "," + item.Value); if (item.Key.Equals("s11")) { dictionary.Remove(item.Key); } }
List<int> intList = new List<int>(); intList.Add(1); intList.Add(2); for(var i=0;i<intList.Count;i++) { if (intList[i] == 1) { intList[i]=3; } Console.WriteLine("集合中元素遍历:" + intList[i]); }
输出:
集合中元素遍历:3 集合中元素遍历:2
从如上输出看出,for修改为功
直接编译就通不过
以下程序,会去修改迭代器元素的属性,而且在for跟foreach下都能运行成功。
class Program { static void Main(string[] args) { List<protocol> protocols = new List<protocol>(); var p1 = new protocol(); p1.bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; var p2 = new protocol(); p2.bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; protocols.Add(p1); protocols.Add(p2); foreach (var item in protocols) { item.bytes = p2.bytes; item.intList.Add(1); } for (var i=0;i<protocols.Count;i++) { protocols[i].bytes = p1.bytes; protocols[i].intList.Add(1); protocols[i] = p1; } Console.WriteLine("程序运行成功"); Console.ReadLine(); } } public class protocol { public byte[] bytes= { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; public List<int> intList=new List<int>(); }
既然,for效率更高,foreach效率不及for。for能作的事foreach不能作(修改删除元素)。是否是没有foreach的用武之地了呢,大错特错了,偏偏相反,每一个项目里用的最多的反而是foreach迭代器模式,我统计了下超过工厂模式跟单例模式,不信你本身去数foreach的数量。可是在遍历散列集合时,如字典,for就会失效了,由于下标不是有序数值了,而是看上去无序的内部散列算法。这时foreach遍历字典就颇有用,他定义了一个枚举器(迭代器),而这个枚举器统一了,getCurrent(), moveNext()等用于迭代的方法;
foreach (var item in dictionary.ToList()) { Debug.Log(item.Key + "," + item.Value); if (item.Key.Equals("s11")) { dictionary.Remove(item.Key); } }
像上面的用for,for循环的i与字典的key(自定义,通常是string类型)是没办法创建映射关系的;因此没法用for循环
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。 本文连接:http://www.javashuo.com/article/p-odyaqksf-nv.html