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

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

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

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

该接口的方法

public interface IEnumerable

    {

        // 摘要:

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

        //

        // 返回结果:

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

        [DispId(-)]

        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默认将集合的索引指向前一个

        ;

        //05实现接口的Movenext方法

        public bool MoveNext()

        {

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

             > index)

            {

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

                index++;

                //改变bool值为true

                happy = true;

            }

            return happy;

        }

        public void Reset()

        {

            index = -;

        }

    }
 MyList list=new MyList();

     list.Add("小王");

     list.Add("小李");

     foreach (string item in list)

     {

         Console.WriteLine(item);

      }

    Console.ReadKey();

探讨关于C#中Foreach的本质的更多相关文章

  1. 接口、索引器、Foreach的本质(学习笔记)

    接口 什么是接口? 接口代表一种能力,和抽象类类似但比抽象类的抽象程度更高! 接口的定义: public interface IEat//定义一个接口 { void Eat(string food); ...

  2. C#中foreach的实现原理

    C#中foreach的实现原理 在探讨foreach如何内部如何实现这个问题之前,我们需要理解两个C#里边的接口,IEnumerable 与 IEnumerator. 在C#里边的遍历集合时用到的相关 ...

  3. ecshop中foreach的详细用法归纳

    ec模版中foreach的常见用法. foreach 语法: 假如后台:$smarty->assign('test',$test); {foreach from=$test item=list ...

  4. mybatis中foreach的用法(转)

    foreach一共有三种类型,分别为List,[](array),Map三种. foreach属性 属性 描述 item 循环体中的具体对象.支持属性的点路径访问,如item.age,item.inf ...

  5. thinkphp模板中foreach循环没数据的错误解决

    从控制器方法中$this->assign();函数将值传递给html模板 但是模板不显示数据,直接出来的是代码,效果就和html中写了php代码不能解析一样. 原来是我将thinkphp框架的引 ...

  6. c语言中函数调用的本质从汇编角度分析

    今天下午写篇博客吧,分析分析c语言中函数调用的本质,首先我们知道c语言中函数的本质就是一段代码,但是给这段代码起了一个名字,这个名字就是他的的这段代码的开始地址 这也是函数名的本质,其实也就是汇编中的 ...

  7. php中foreach()函数与Array数组经典案例讲解

    //php中foreach()函数与Array数组经典案例讲解 function getVal($v) { return $v; //可以加任意检查代码,列入要求$v必须是数字,或过滤非法字符串等.} ...

  8. PHP中foreach()用法汇总

    这篇文章主要给大家详细介绍了PHP中foreach()用法以及相关的示例,十分的细致,有需要的小伙伴可以参考下. PHP 4 引入了 foreach 结构,和 Perl 以及其他语言很像.这只是一种遍 ...

  9. flask中路由的本质源码分析

    flask中url的本质: 吧url和视图函数封装到一个Rule对象里面去了,并且吧这个对象添加到url_map中 Rule={"url":'/index','method':'i ...

随机推荐

  1. 一款WP小游戏代码分享

    首先声明游戏是H5的代码,当然游戏部分不是我写的,感谢@LeZhi的分享,关于H5我还在学习,这里只是简单介绍一下如何把一款现成的H5游戏封装成一款WP游戏(当然也可以做成Windows游戏). 大家 ...

  2. SQL替换语句之批量修改、增加、删除字段内容

    语法 REPLACE ( original-string, search-string, replace-string ) 用法 update 表的名称 set 替换字段=REPLACE(替换字段,原 ...

  3. setter方法的内存错误

    - (void)setList:(ClassicList *)list { self.list = list; _titleLabel.text = list.activityName; _addre ...

  4. 每天一个linux命令(29):date命令

    在linux环境中,不管是编程还是其他维护,时间是必不可少的,也经常会用到时间的运算,熟练运用date命令来表示自己想要表示的时间,肯定可以给自己的工作带来诸多方便. 1.命令格式: date [参数 ...

  5. 每天一个linux命令(14):which命令

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索:        which  查看可执行文件的位置.       whereis 查看文件的位置.         ...

  6. Qt webkit插件相关知识

    1.在Qt中使用 WebKit 浏览器核心 使用 QtWebKit 需要在工程文件(*.pro)中加入: 1.           QT +=webkit   2.           QT += n ...

  7. C#中async/await中的异常处理

    在同步编程中,一旦出现错误就会抛出异常,我们可以使用try-catch来捕捉异常,而未被捕获的异常则会不断向上传递,形成一个简单而统一的错误处理机制.不过对于异步编程来说,异常处理一直是件麻烦的事情, ...

  8. Maven-在eclipse中安装Maven插件

    装IDE Plugins的方法有很多. 其一:在线安装 通过Help-->Install New Software的方式,输入HTTP地址来安装,简单易操作,但是也优缺点,就是下载速度慢,或者有 ...

  9. Unix/Linux 命令技巧

    锁定一个文件夹 为了我的数据隐私,我想要锁定我文件服务器下的/downloads文件夹.因此我运行了: chmod 0000 /downloads root用户仍旧可以访问,而ls和cd命令则不工作. ...

  10. CRUD之delete操作

    在公司的项目中delete之后的操作有两种处理方式 1.后台删除成功之后前台页面刷新 2.后台删除成功之后页面不刷新,但是数据所在的那个div会刷新一次 3.后台删除,页面上做了一个删除,删除的td没 ...