认识foreach
初学者往往不明白为什么c#里有for来处理循环了,还要提供一个foreach。难道仅仅是因为让语法简单明了,提高那么点性能?当然不是那么简单,foreach的设计有他独到之处。foreach和for的循环方式不太一样,这里不再赘述,如果你理解循环和迭代的不同之处,那么一句话就可以区分两者的区别了,for是循环,foreach是迭代。
要了解foreach的独到之处一定要了解yield,我们看语法就能明白这两者肯定是有联系的,foreach循环的对象必须是实现了IEnumerable或IEnumerable
private static int[] Fibonacci() { int[] fibNumbers = new int[5]; fibNumbers[0] = 1; fibNumbers[1] = 1; for (int i=2; i<5; i++) { fibNumbers[i] = fibNumbers[i-1] + fibNumbers[i-2]; } return fibNumbers; }
然后循环输出该数列
var fibNums = Fibonacci(); for (int i=0; i) { Console.WriteLine(fibNums[i]); }
上面的代码有一个问题,就是我会执行2次循环,如果外面又套了几层,那就会循环多次,而且数量大了后,那就很影响性能了。foreach的独到之处就在于让他只循环一次,当然得配合yield。修改生成数列代码
private static IEnumerable<int> Fibonacci() { int[] fibNumbers = new int[5]; fibNumbers[0] = 1; yield return 1; fibNumbers[1] = 1; yield return 1; for (int i=2; i<5; i++) { fibNumbers[i] = fibNumbers[i-1] + fibNumbers[i-2]; yield return fibNumbers[i]; } }
修改输出代码为foreach
foreach (var i in Fibonacci()) { Console.WriteLine(i); }
如果调用Fibonacci方法后又调用了ToArray或ToList再执行foreach那就前功尽弃了,调用ToArray或ToList会执行迭代器做一遍循环生成数组或集合,再做foreach那又会对数组或集合再做一次循环,又变2次循环了。所以我们在碰到返回IEnumerable接口的方法时不要急着ToArray或ToList,还有也不要随意Count(),那都会执行一遍循环从而影响性能。最常见的就是EF中获取集合返回的都是IEnumerable,如果你ToList了再做循环处理数据那就得不偿失了。