我想大家都应该用过foreach吧。其实foreach就是一种迭代的调用。在这里,我们将讨论一个基本迭代的组成。
为了实现枚举,一个可枚举的(enumerable)的集合要有一个无参的、返回枚举器(enumerator)的GetEnumerator方法。
而要获得枚举器,我们就需要一个迭代器。所谓迭代器,就是一个可以产生有序的值序列的语句块。这里,我们就需要引入yield上下文关键字。其中,yield return产生本次迭代的值,yield break指示本次迭代完成。
创建迭代器一般有两种方法:
1.对可枚举接口(即IEnumerable和IEnumerable<T>)实现GetEnumerator方法,然后对该类直接使用foreach迭代。
2.创建一个返回可枚举接口(即IEnumerable和IEnumerable<T>)的函数,对该函数的返回值使用foreach迭代。
通过这两种方式,访问数据集合。
以下,将分别举例阐述:
1.实现GetEnumerator方法。
public class ListSample<T> : IEnumrable<T>{
private T[] items;
...//some methods to modify items
public IEnumerator<T> GetEnumerator(){
for(int i=0; i<items.Length; i++){
yield return items[i];
}
}
}
这样便完成了迭代器,然后便可以通过foreach语句迭代该类返回items中的所有元素。
ListSample<int> list = new ListSample<int>();
foreach(int i in list){
Console.WriteLine(i);
}
2.创建迭代函数
public class ListSample<T>{
private T[] items;
...//some methods to modify items
public IEnumerable<T> Iterator(){
for(int i=0; i<items.Length; i++){
yield return items[i];
}
}
}
这样,我们就可以通过Iterator的返回值进行迭代。
ListSample<int> list = new ListSample<int>();
foreach(int i in list.Iterator()){
Console.WriteLine(i);
}
第一种方法的优点就是设计方便简单,直接实现IEnumerable或者IEnumerable<T>即可;第二种方法的自由度大,可以自行为函数设定参数表,来自定义迭代的范围等等。
然后说一下基本注意事项吧:
1.yield语句不能用于匿名方法,yield语句不能用于finally块中,yield return不能用于try...catch块中。
2.迭代函数的参数中不能出现ref或者out。
其它的内容,诸如MoveNext()等方法的具体实现以及异常处理块中的情况讨论等问题由于较为复杂且平时不常用到,这里暂不讨论。有兴趣可以参考微软相关文献。
为了实现枚举,一个可枚举的(enumerable)的集合要有一个无参的、返回枚举器(enumerator)的GetEnumerator方法。
而要获得枚举器,我们就需要一个迭代器。所谓迭代器,就是一个可以产生有序的值序列的语句块。这里,我们就需要引入yield上下文关键字。其中,yield return产生本次迭代的值,yield break指示本次迭代完成。
创建迭代器一般有两种方法:
1.对可枚举接口(即IEnumerable和IEnumerable<T>)实现GetEnumerator方法,然后对该类直接使用foreach迭代。
2.创建一个返回可枚举接口(即IEnumerable和IEnumerable<T>)的函数,对该函数的返回值使用foreach迭代。
通过这两种方式,访问数据集合。
以下,将分别举例阐述:
1.实现GetEnumerator方法。
public class ListSample<T> : IEnumrable<T>{
private T[] items;
...//some methods to modify items
public IEnumerator<T> GetEnumerator(){
for(int i=0; i<items.Length; i++){
yield return items[i];
}
}
}
这样便完成了迭代器,然后便可以通过foreach语句迭代该类返回items中的所有元素。
ListSample<int> list = new ListSample<int>();
foreach(int i in list){
Console.WriteLine(i);
}
2.创建迭代函数
public class ListSample<T>{
private T[] items;
...//some methods to modify items
public IEnumerable<T> Iterator(){
for(int i=0; i<items.Length; i++){
yield return items[i];
}
}
}
这样,我们就可以通过Iterator的返回值进行迭代。
ListSample<int> list = new ListSample<int>();
foreach(int i in list.Iterator()){
Console.WriteLine(i);
}
第一种方法的优点就是设计方便简单,直接实现IEnumerable或者IEnumerable<T>即可;第二种方法的自由度大,可以自行为函数设定参数表,来自定义迭代的范围等等。
然后说一下基本注意事项吧:
1.yield语句不能用于匿名方法,yield语句不能用于finally块中,yield return不能用于try...catch块中。
2.迭代函数的参数中不能出现ref或者out。
其它的内容,诸如MoveNext()等方法的具体实现以及异常处理块中的情况讨论等问题由于较为复杂且平时不常用到,这里暂不讨论。有兴趣可以参考微软相关文献。