C#中foreach实现原理详解
本文主要记录我在学习C#中foreach遍历原理的心得体会。
对集合中的要素进行遍历是所有编码中经常涉及到的操作,因此大部分编程语言都把此过程写进了语法中,比如C#中的foreach。经常会看到下面的遍历代码:
varlstStr=newList{"a","b"}; foreach(varstrinlstStr) { Console.WriteLine(str); }
实际此代码的执行过程:
varlstStr=newList{"a","b"}; IEnumerator enumeratorLst=lstStr.GetEnumerator(); while(enumeratorLst.MoveNext()) { Console.WriteLine(enumeratorLst.Current); }
会发现有GetEnumerator()方法和IEnumerator
为了方便理解,以下为非泛型示例:
//摘要:
//公开枚举器,该枚举器支持在非泛型集合上进行简单迭代。
publicinterfaceIEnumerable
{
//摘要:
//返回一个循环访问集合的枚举器。
//
//返回结果:
//可用于循环访问集合的System.Collections.IEnumerator对象。
IEnumeratorGetEnumerator();
}
实现了此接口的类称为可枚举类型,是可以用foreach进行遍历的标志。
方法GetEnumerator()的返回值是枚举器,可以理解为游标。
//摘要:
//支持对非泛型集合的简单迭代。
publicinterfaceIEnumerator
{
//摘要:
//获取集合中的当前元素。
//
//返回结果:
//集合中的当前元素。
//
//异常:
//System.InvalidOperationException:
//枚举数定位在该集合的第一个元素之前或最后一个元素之后。
objectCurrent{get;}
//摘要:
//将枚举数推进到集合的下一个元素。
//
//返回结果:
//如果枚举数成功地推进到下一个元素,则为true;如果枚举数越过集合的结尾,则为false。
//
//异常:
//System.InvalidOperationException:
//在创建了枚举数后集合被修改了。
boolMoveNext();
//
//摘要:
//将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
//
//异常:
//System.InvalidOperationException:
//在创建了枚举数后集合被修改了。
voidReset();
}
以下是自定义一个迭代器的示例(https://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx):
usingSystem;
usingSystem.Collections;
//Simplebusinessobject.
publicclassPerson
{
publicPerson(stringfName,stringlName)
{
this.firstName=fName;
this.lastName=lName;
}
publicstringfirstName;
publicstringlastName;
}
//CollectionofPersonobjects.Thisclass
//implementsIEnumerablesothatitcanbeused
//withForEachsyntax.
publicclassPeople:IEnumerable
{
privatePerson[]_people;
publicPeople(Person[]pArray)
{
_people=newPerson[pArray.Length];
for(inti=0;i
在有了yield这个关键字以后,我们可以通过这样的方式来创建枚举器:
usingSystem;
usingSystem.Collections;
//Simplebusinessobject.
publicclassPerson
{
publicPerson(stringfName,stringlName)
{
this.firstName=fName;
this.lastName=lName;
}
publicstringfirstName;
publicstringlastName;
}
//CollectionofPersonobjects.Thisclass
//implementsIEnumerablesothatitcanbeused
//withForEachsyntax.
publicclassPeople:IEnumerable
{
privatePerson[]_people;
publicPeople(Person[]pArray)
{
_people=newPerson[pArray.Length];
for(inti=0;i
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。