码迷,mamicode.com
首页 > 其他好文 > 详细

有关foreach的一些想法

时间:2014-06-02 11:56:02      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:c   class   a   ext   int   get   

在C#中,foreach的使用简化了很多循环语法的书写。如果我们仅仅把foreach当成for循环的省略写法的话,就显得有点大才小用了。

事实上,foreach与“迭代”和“枚举”密切相关。

C#编译器会把foreach语句转换为IEnumerable接口的方法和属性。

例如:

 foreach (var p in persons)            

{

Console.WriteLine(p);     

}

以上代码迭代persons数组中的所有元素,并逐个显示他们。

foreach语句会解析成下面的代码。首先调用GetEnumerator()方法,获得数组的一个枚举。

在while循环中(只要MoveNext()返回true),用Current属性访问数组中的元素:

IEnumerator enumerator = persons.GetEnumerator();            

while (enumerator.MoveNext())            

{                

Person p = (Person) enumerator.Current; Console.WriteLine(p);            

}

这里要说明的是。用[]声明数组是C#中使用Array类的记号。Array类实现了IEnumerable接口中的GetEnumerator()方法。

所以使用foreach语句迭代数组,其实是使用了Array类中个GetEnumerator()方法。

也就是说,只要是实现了IEnumerable接口中的GetEnumerator()方法的类,都可以用foreach语句来迭代。

IEnumerable接口中的GetEnumerator()方法是这样定义的:

IEnumerator GetEnumerator()

其返回的类型是一个IEnumerator接口。

IEnumerator接口中的Current属性返回光标所在的元素。

IEnumerator接口中的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true。如果集合不再有更多的元素,该方法就返回false。

IEnumerator接口中的Reset()方法将光标重新定位于集合的开头。许多枚举会抛出NotSupportedException异常。

下面,我们来写一个实现了IEnumerable接口的类。

 public class HelloCollection:IEnumerable                    

{                        

    public IEnumerator GetEnumerator()                        

   {                            

     yield return "Hello";                            

     yield return "World";                        

   }                    

}

现在可以用foreach语句迭代了:

static void Main(string[] args)        

{

         HelloCollection helloCollection=new HelloCollection ();            

         foreach (string s in helloCollection )            

         {                

         Console.WriteLine(s);            

         }        

}

实际上,yield return语句返回集合的一个元素,并移动到下一个元素上。它会将类HelloCollection解析成如下代码:

 public class HelloCollection : IEnumerable        

{            

    public IEnumerator GetEnumerator()            

   {                

      Enumertor enumerator = new Enumerator();                

      return enumerator;            

   }

   public class Enumertor : IEnumerator, IDisposable            

  {                

      private int state;                

      private object current;

      public Enumertor(int state)                

     {                    

        this.state = state;                

     }            

  }                

     bool System.Collections .IEnumerator .MoveNext()                

   {                    

     switch (state)                    

       {                        

          case 0:                            

          current = "Hello";                            

          state = 1;                            

          return true;                        

          case 1:                            

          current = "World";                           

         state = 2;                            

         return true ;                        

         case 2:                            

         break ;                    

      }                    

    return false ;                

    }

  void System.Collections .IEnumerator .Reset()                

   {                    

     throw new NotSupportedException();                

   }

  object System.Collections .IEnumerator .Current                

  {                    

      get 

         {

            return current;

         }                

    }                

void IDisposable.Dispose()                

   {                

   }        

}

 

 

 

foreach语句默认用GetEnumerator()方法迭代,也可以自行制定迭代方法。举例:

public class MusicTitles:IEnumerable        

{            

   string[] names = { "Tubular Bells", "Hergest Ridge", "Ommadawn", "Platinum" };

   public IEnumerator GetEnumerator()  /*顺序迭代*/            

   {                

     for (int i = 0; i < 4; i++)                    

     yield return names[i];            

    }

   public IEnumerator Reverse()  /*逆序迭代*/            

    {                

       for (int i = 3; i >= 0; i--)                    

       yield return names[i];            

    }        

}

在foreach语句中不必写明使用GetEnumerator()方法迭代,因为这是默认方法。如下:

static void Main(string[] args)        

{

    MusicTitles titles = new MusicTitles();            

    foreach (string title in titles)            

    {                

      Console.WriteLine(title);            

     }

    Console.WriteLine();

    foreach (string title in titles.Reverse())            

    {                

     Console.WriteLine(title);            

    }        

}

有关foreach的一些想法,布布扣,bubuko.com

有关foreach的一些想法

标签:c   class   a   ext   int   get   

原文地址:http://www.cnblogs.com/yellow-Li/p/3764158.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!