zoukankan      html  css  js  c++  java
  • 探讨关于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();

     

      

     

  • 相关阅读:
    素数判定方法,方法持续更新...
    C++暂停黑窗口
    【python爬虫】scrapy入门6-生成多个spider
    【python爬虫】scrapy入门5--xpath等后面接正则
    python基础:list与string互转
    【python爬虫】scrapy实战1--百万微博任性采集
    【python爬虫】scrapy入门4--添加cookies
    【python爬虫】scrapy入门2--自定义item
    【python爬虫】scrapy入门1--环境搭建
    sklearn学习:为什么roc_auc_score()和auc()有不同的结果?
  • 原文地址:https://www.cnblogs.com/hyjj/p/5387103.html
Copyright © 2011-2022 走看看