今天写关于foreach的一些东西包括一下内容
foreach的介绍
foreach的简单用法
手工实现 IEnumerator 和 IEnumerable接口来兼容foreach
yield return关键字和迭代器
foreach的介绍
类似与for语句遍历集合(数组等数据结构)的语句。
看一下masn的介绍”foreach 语句对实现 System.Collections. IEnumerable 或 System.Collections.Generic. IEnumerable< T> 接口对象集合中的每个元素重复一组嵌入式语句”
另外在遍历过程中可以使用 break continue goto return throw这些方式在中途退出
很重要的一点是利用foreach只能实现只读,要修改集合中的内容就必须用for
更重要的是它的速度比用for语句快
关于效率问题可以参考《深入探讨C#foreach语句》的前半部分
文章地址:http://developer.51cto.com/art/200908/147347.htm
foreach的简单用法
直接上代码
比较值得注意是交错数组部分
因为交错数组是数组的数组
所以代码中a3类型是int[][] a的类型是int[] e的类型是int
手工实现 IEnumerator 和 IEnumerable接口来兼容foreach
讲这个之前先讲一下foreach的原理(一下来自《C#入门经典》)
(1)调用collectionObject.GetEnumerator(),返回一个IEnumerator引用。这个方法可以通过IEnumerable接口的实现代码来获得。但这是可选的。
(2)调用返回的IEnumerator接口的MoveNext()方法。
(3)如果MoveNext()方法返回true,就使用IEnumerator接口的Current属性获取对象的一个引用,用于foreach循环。
(4)重复前面两步,直到MoveNext()方法返回false为止,此时循环停止。
那么如果你要为自己建立的集合提供foreach语句的支持,按照MSDN的说法应该“在 C# 中,集合类并非必须严格从 IEnumerable 和 IEnumerator 继承才能与 foreach 兼容;只要类有所需的 GetEnumerator 、MoveNext 、Reset 和 Current 成员,便可以与 foreach 一起使用。省略接口的好处为,使您可以将 Current 的返回类型定义得比 object 更明确,从而提供了类型安全。”
我们先来看一下这两个接口的定义
只要我们的集合类能实现这两个接口就可以使用foreach对集合进行遍历
具体的代码如下
如果还有不清楚可以对比一下MSDN中的实例
http://msdn.microsoft.com/zh-cn/library/9yb8xew9%28v=VS.80%29.aspx
yield return关键字和迭代器
如果为了让集合支持foreach语句要多出那么一大块的代码,确是有点麻烦。
所以自然有一种简单的办法出现了,使用迭代器。
这东西可以再后台帮你生成很多代码
在为类或结构创建迭代器时,不必实现整个 IEnumerator 接口。
当编译器检测到迭代器时,它将自动生成 IEnumerator 接口的 Current 、MoveNext 和 Dispose 方法。
然后利用yield return语句依次返回每个元素,选择要在foreach循环中使用的值。
到达yield return语句时,会保存当前迭代的位置,下次调用迭代器时将从此位置开始执行。
那如何创建一个迭代器块呢?
也很简单yield 关键字就是向编译器指示它所在的方法是迭代器块。
不知道这样写有没有表达清楚,还是代码来的直接点
实现了一个打印素数的功能。
值得一提的是,那些数是一个一个出来的。可以再输出语句后再加输出点东西就看出来了
也就是迭代器一次只返回一个结果,调用yield的时候会中断代码的执行,等foreach开始新的循环代码才回复执行。
同时也给一段比较短的代码作为对照
如果有心的话应该可以猜到 yield return 返回的是一个object类型的值。所以不用再自己指定了。
。