IEnumerator,IEnumerable接口,yield关键字

foreach可以迭代一些.net本来就为我们做好的类型,比如int,string等等

但是如果想迭代自己的类,就必须自己来写了

首先就要先实现IEnumerator的几个方法,和IEnumerable的GetEnumerator()方法

 

代码
foreach (person p  in  persons)
{
   console.writeline(p)
}
//会解析为
IEnumerator enumerator 
=  persons.GetEnumerator();
while (enumerator.MoveNext())
{
   Person p 
=  (Person)enumerator.Current;
   Console.WriteLine(p);
}

 

 

也就是说,foreach循环会调用IEnumerator下的几个方法

他们分别是:public bool MoveNext(),public void Reset(), public object Current属性

顾名思义

 

代码
   public   class  Person
    {
        
public  Person( string  fName,  string  lName)
        {
            
this .firstName  =  fName;
            
this .lastName  =  lName;
        }

        
public   string  firstName;
        
public   string  lastName;
    }

    
public   class  People : IEnumerable
    {
        
private  Person[] _people;
        
public  People(Person[] pArray)
        {
            
// _people=pArray?????????
            _people  =   new  Person[pArray.Length];

            
for  ( int  i  =   0 ; i  <  pArray.Length; i ++ )
            {
                _people[i] 
=  pArray[i];
            }
        }
        
///   <summary>
        
///  接口的实现,返回的是一个PeopleEnum的一个类对象
        
///   </summary>
        
///   <returns></returns>
         public  IEnumerator GetEnumerator()
        {
            
return   new  PeopleEnum(_people);
        }
    }

    
public   class  PeopleEnum : IEnumerator
    {
        
public  Person[] _people;

        
//  Enumerators are positioned before the first element
        
//  until the first MoveNext() call.
         int  position  =   - 1 ;

        
public  PeopleEnum(Person[] list)
        {
            _people 
=  list;
        }

        
public   bool  MoveNext()
        {
            position
++ ;
            
return  (position  <  _people.Length);
        }

        
public   void  Reset()
        {
            position 
=   - 1 ;
        }

        
public   object  Current
        {
            
get
            {
                
try
                {
                    
return  _people[position];
                }
                
catch  (IndexOutOfRangeException)
                {
                    
throw   new  InvalidOperationException();
                }
            }
        }
    }

    
class  App
    {
        
static   void  Main()
        {
            Person[] peopleArray 
=   new  Person[ 3 ]
            {
               
new  Person( " John " " Smith " ),
               
new  Person( " Jim " " Johnson " ),
               
new  Person( " Sue " " Rabon " ),
            };

            People peopleList 
=   new  People(peopleArray);
            
foreach  (Person p  in  peopleList)
            {
                Console.WriteLine(p.firstName 
+   "   "   +  p.lastName);
            }
            Console.Read();
        }
    }

 

总结: 迭代自定义的类,必须实现实现GetEnumerator()方法返回IEnumerator

IEnumerator提供了foreach使用的方法属性

 

 

 

C#2.0有了yield关键字,就不用每次都这样实现IEnumerator接口了
包含yield语句的方法必须返回IEnumerator或者IEnumerable接口
 

代码
    public   class  person
    {
        
private   string  _Name;
        
public   string  Name {  get set ; } 
        
public  person( string  name)
        {
            Name 
=  name;
        }
        
public   override   string  ToString()
        {
            
return   this .Name;
        }
    }
    
class  people
    {
        
private  person[] _person;
        
public  people(person[] person)
        {
            _person 
=  person;
        }
        
public  IEnumerator GetEnumerator()
        {
            
for  ( int  i  =   0 ; i  <  _person.Length; i ++ )
            {
                
yield   return  _person[i];
            }
        }
        
public  IEnumerable reverse()
        {
            
for  ( int  i  =  _person.Length  -   1 ; i  >=   0 ; i -- )
            {
                
yield   return  _person[i];
            }
        }
    }
    
class  Program
    {
        
static   void  Main( string [] args)
        {
            person[] p 
=   new  person[ 3 ]
            {
               
new  person( " John " ),
               
new  person( " Jim " ),
               
new  person( " Sue " ),
            };
            people pp 
=   new  people(p);
            
foreach  (person pe  in  pp)
            {
                Console.WriteLine(pe);
            }
            
foreach  (person ppp  in  pp.reverse())
            {
                Console.WriteLine(ppp);
            }

            Console.Read();
        }
    }

 

 

我认为yield关键字帮助我们实现了IEnumerator的方法

也可以自己定义迭代的方式,比如以上代码就实现了逆向循环。

 

参考:C#红皮书

  

你可能感兴趣的:(yield)