黑马程序员_学习日记9_C#基础归纳之foreach迭代

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

 

枚举:

 在foreach中使用迭代块对集合和数组进行枚举,无需知道集合数组中具体的元素个数。

原因是 数组和集合实现了带GetEnmumerator()方法的IEumerable接口。GetEnumerator()

实现了IEumnerable接口的枚举。

 

和foreach接口枚举相关的两个重要接口为:

IEnumerable 和IEnumerator(它们也都支持泛型)

 

IEnumerable接口源代码定义:

interface IEnumerable
{
      //返回一个类型为IEnumerator的计算器
     IEnumerator GetEnumerator();
 
}


IEnumerator接口的源代码定义:

Interface IEnumerator
{
       //当前枚举的对象
       Object Current{get;}
       //确定枚举对象是否存在,并将计数器指到下一个枚举对象
        bool  MoveNext();

       //Reset();
}


我们发现IEnumerable接口中定义的是一个方法名为GetEnumerator,返回类型为IEnumerator的方法定义。

紧接着 IEnumerator接口中就定义了Current   ,MoveNext()等属性和方法,也就是说,你实现了IEnmerable接口

就必须要实现Current ,MoveNext(),Reset()的方法。

 

GetEnumerator()用接口IEnumerable接口定义,foreach并不需要被迭代的对象必须实现这个接口,

只需要该对象中有一个名为GetEnumerator(),且返回类型为IEnumerator的方法就行。

 

foreach语句:

C#中foreacach语句不会解析为IL中的foreach语句,C#编译器会把foreach语句解析为实现了IEnumerable接口的方法和属性

 

Peson[ ]   Persons = { new Person("tom",21),new Person("jack",25)};

 

foreach (person p in persons)

{

         Console.WriteLine(P.FirstName);

}

这条语句并不是原本不动的映射到IL中,它会转化为一个这样的模式。

IEnumerator<Person> MyEnum = Persons.GetEnumerator();

while(MyEnum.MoveNext())

{

      Person p = MyEnum,Current;

     Console.WriteLine(p.FirstName);

}

 

使用foreach对数据进行迭代时,首先会调用GetEnumerator()方法,来返回一个类型为IEnumerator的计数器,

接着使用技术器的MoveNext()方法对数据中的每一项数据进行枚举。

 

 

yield语句:

yield语句是C#2.0时引入的一个语法,它能使我们轻松的创建一个枚举器。这是为了简化实现枚举器的步骤,否则你需要实现IEnumerable和IEnumerator两个接口。

public class hellcollection
{
       public IEnumerator<string> GetEnumerator()
      {
                       yield return "hello";
                       yield return "world";
      }
}


我们就可以使用foreach语句对hellocollection对象进行迭代了

var hellco = new hellection();

foreach(string s in hellco)

{

      Console.WriteLine(s);

}

 

那么yield return语句到底帮我们做了些什么事情,可以使我们能够使用foreach对该对象进行迭代呢?

在C#中使用yield return语句,会生成一个包含一个状态机的迭代类型计数器。

yield 类型实现了IEnumerator和IDispose接口。我们可以把yield看成是C#编译器帮我们实现了IEnumerator接口

和IDispose接口的一个对象。

上面的例子,实际实现是下面这样的情况。

public class hellcollection

{

      public IEnumerator GetEnumerator()

      {

             return Enumerator(0);//返回一个计数器

     }

 

   public class Enumerator:IEnumerator<string>,IDispose,IEnumerator//定义一个内部类来实现枚举器的属性和方法

   {

                private int state ;//状态机表示当前美剧状态

               private string current;//当前枚举的对象值

             

               public Enumerator(int state)

              {

                     this.state = state;

             }

 

           public bool MoveNext()

            {

                      swith(state)

                      {

                                case 0:

                                current="hello";

                                state=1;

                                return true;

                                case 1:

                                current="world";

                                state=2;

                                return true;

                                case 3:

                                break;

                       }

                    return false;

           }

    public   string Current

     {

            get{return  current;}

    }

 

 

  //...........还有一些别的接口的方法实现 我就不写了。

  }

}

 

 

迭代集合的不同方式:

可以使用yield return语句,以不同的方式迭代集合

public class MusicTitles

{

        string[ ] names = {"套马杆","凤凰传奇","伤不起"};

      

        //正序迭代 

       public IEnumerator<string> GetEnumerator()

       {

                    for(int i=0;i<names.Length;i++)

                     {

                               yield return names[i];

                    }

      }

    

    //逆序迭代

    public IEnumerable<string> Reverse()

    {

            for(var i=names.Length;i>=0;i--)

             {

                     yield return names[i];

            }

    }

 

  //部分迭代

  public IEnumerable<string> Sub(int index,int length)

  {

            for(int i=index;i<index+Length;i++)

            {

                     yield return names[i];

            }

 }

   

}

第一个迭代的类型的返回值为IEnumerator,其他的则为IEnumerable 我的个人理解是

IEnumerator已经为我们定义好了迭代模板,无需再次定义,所以后面的迭代直接调用其

定义好的模板即可,无需在使自己的返回类型为IEnumerator ,而为IEnumerable即可。

 

类支持的默认迭代返回计数器的方法为GetEnumerator()方法。

 

下面我们对上述例子进行各种形式的迭代。

第一种:

var musicEnum = new MusicTitles();

foreach(var title in musicEnum)

{

        Console.WriteLine(title);

}

第二种:

foreach(var title in musicEnum.Reverse())

{

       Console.WriteLine(title);

}

第三种:

foreach(var title in musicEnum.Sub(1,2))

{

       Console.WriteLine(title);

}

 

---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------
详细请查看: http://net.itheima.com/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值