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 { getset; } 
        
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#红皮书

  

posted @ 2009-12-24 23:56  小白.net  阅读(756)  评论(0编辑  收藏  举报