探讨关于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();

本文永久更新链接地址

相关内容