编程算法-.NET学习之Foreach

对于.NET Framework中的循环使用“算得上”是很熟练了,但今天看了书才发现自己对其一点也不了解……

对于.NET Framework提供的“标准”的集合类型可以直接使用foreach,如(Array、ArrayList、HashTable),除此之外,对于自定义的集合对象,也可以使其支持foreach的使用,只要实现IEnumerable接口即可(刚提到的几种集合类型都实现了这个接口)。

运行可以看到正确的输出了“Hello……  World……”,问题的关键就在 “IEnumerator”的 “IEnumerable.GetEnumerator()”这个方法,以及yield关键字,单步运行程序会发现程序运行至foreach语句之后跳转至HelloCollection中的GetEnumerator方法,然后遇到“yield  return”就返回,接着执行下一个,直到返回所有的yield……

修改上述代码,比方说改为如下代码,先猜测下结果,然后运行看输出什么。

结果输出的是

跳转至GetEnumerator方法
即将输出:
foreach方法
Hello
下一个输出:
foreach方法
World

看明白了?遇到一个yield return 就返回到foreach,而且在foreach内部使用的s就是返回的值。

再看个代码

通过查找可以知道IEnumerable里就一个方法是IEnumerator GetEnumerator();而IEnumerator接口原型如下(查询VS2008文档得知)

C# 语言的 foreach 语句(在 Visual Basic 中为 For Each)隐藏了枚举数的复杂性。因此,建议使用 foreach,而不直接操作枚举数。

枚举数可用于读取集合中的数据,但不能用于修改基础集合。

最初,枚举数定位在集合中第一个元素前。Reset 方法还会将枚举数返回到此位置。在此位置上,Current 属性未定义。因此,在读取 Current 的值之前,必须调用 MoveNext 方法将枚举数提前到集合的第一个元素。

在调用 MoveNext 或 Reset 之前,Current 返回同一对象。MoveNext 将 Current 设置为下一个元素。

如果 MoveNext 越过集合的末尾,则枚举数将被放置在此集合中最后一个元素的后面,而且 MoveNext 返回 false。当枚举数位于此位置时,对 MoveNext 的后续调用也返回 false。如果上一个 MoveNext 调用返回 false,则 Current 未定义。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext。

只要集合保持不变,枚举数就保持有效。如果对集合进行更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,而且其行为是不确定的。

枚举数没有对集合的独占访问权;因此,枚举通过集合在本质上不是一个线程安全的过程。若要确保枚举过程中的线程安全,可以在整个枚举过程中锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。

最后在加个例子,跟上述相关的

参考书籍:金旭亮的《.NET 2.0 面向对象编程揭秘》

 

俊霖

发表评论

您必须