探讨关于C#中Foreach的本质

一.为什么数组和集合可以使用foreach遍历

01. 因为数组和集合都实现了IEnumerable接口,该接口中只有一个方法,GetEnumerator()

02.数组类型是从抽象基类型 Array 派生的引用类型。由于此类型实现了 IEnumerable ,因此可以对 C# 中的所有数组使用 foreach 迭代。(摘自MSDN)

 二.探讨针对于List集合微软的是怎么实现这个IEnumerable接口的

该接口的方法

public interface IEnumerable

    {

        // 摘要:

        //     返回一个循环访问集合的枚举数。

        //

        // 返回结果:

        //     一个可用于循环访问集合的 System.Collections.IEnumerator 对象。

        [DispId(-4)]

        IEnumerator GetEnumerator();

}

对于GetEnumerator这个方法他的返回值时又是一个接口类型。所以在这里还要看IEnumerator的接口内容。

public interface IEnumerator

    {

        // 摘要:

        //     获取集合中的当前元素。

        //

        // 返回结果:

        //     集合中的当前元素。

        object Current { get; }

 

        // 摘要:

        //     将枚举数推进到集合的下一个元素。

        //

        // 返回结果:

        //     如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。

        //

        // 异常:

        //   System.InvalidOperationException:

        //     在创建了枚举数后集合被修改了。

        bool MoveNext();

        //

        // 摘要:

        //     将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。

        //

        // 异常:

        //   System.InvalidOperationException:

        //     在创建了枚举数后集合被修改了。

        void Reset();

    }

所以不难发现微软是通过这种方法的实现遍历迭代变量的

三.通过C#代码实现自定义类型的集合遍历

首先该类必须实现IEnumerable接口

 //01自定义类型:实现IEnumerable接口,证明这个类型保存的数据能被foreach遍历

    //IEnumberable这个接口,在微软底层有一个方法GetEnumerator()返回值类型是IEnumerator接口

    public class MyList:IEnumerable

    {

        //02定义一个集合

        ArrayList list=new ArrayList();

        //03实现IEnumberable的方法

        public IEnumerator GetEnumerator()

        {

           return new MyIEnumerator(list);

        }

 

        public void Add(Object oj)

        {

            list.Add(oj);

        }

}
//IEnumerator:支持对非泛型集合的简单迭代

    public class MyIEnumerator:IEnumerator

    {

        //01定义一个List集合

        ArrayList list=new ArrayList();

        //02无参构造

        public MyIEnumerator(ArrayList list)

        {

            //跟当前类的集合赋值

            this.list = list;

        }

 

        public object Current

        {

            get { return list[index]; }

        }

        //04默认将集合的索引指向前一个

        private int index = -1;

        //05实现接口的Movenext方法

        public bool MoveNext()

        {

            bool happy = false;//默认为没有数据

            if (list.Count - 1 > index)

            {

                //证明集合中有数据让索引加1

                index++;

                //改变bool值为true

                happy = true;

            }

            return happy;

        }

 

        public void Reset()

        {

            index = -1;

 

        }

    }
 MyList list=new MyList();

     list.Add("小王");

     list.Add("小李");

     foreach (string item in list)

     {

         Console.WriteLine(item);

      }

    Console.ReadKey();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊小何同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值