zoukankan      html  css  js  c++  java
  • 说下IEnumerable相关的

    IEnumerable

    我们每天都在使用foreach进行遍历,今天讨论下面三个常见的问题:

    • 为什么在foreach中不能修改item的值
    • 要实现foreach需要满足什么条件
    • 为什么Linq to Object中要返回IEnumerable类型

    接下来,进入正题,首先我们先剖析下迭代器的内容,首先让我们创建一个迭代器

    实现迭代器

    .net中迭代器是通过IEnumerable和IEnumerator接口来实现的。首先让我们看下两个接口的面目

    可以看出,IEnumerable只有一个返回了IEnumerator的方法GetEnumerator(),而IEnumerator中有两个方法加一个属性:MoveNext(),Reset(),Current

    我们自己继承IEnumerable接口并实现:

    下面使用原始的方式调用:

    可以看出分了三步:①获取IEnumerator接口实例,②判断是否可以继续循环,③取值

    有朋友开始说了,我们平时都是通过foreach来取值的,没有这样使用过啊。好吧,我们来使用foreach循环:

    效果是等效的,通过反编译可以看出:

    由此可见,两者有这么个关系:

    我们可以回答第一个问题了“为什么在foreach中不能修改item的值?”:

    我们还记得IEnumerator的定义吗

    接口的定义就只有get没有set。所以我们在foreach中不能修改item的值。

    我们再来回答第二个问题:“要实现foreach需要满足什么条件?”:

    是否必须实现IEnumerable接口?

    答案是否。我们自己写的MyIEnumerable删掉后面的IEnumerable接口一样可以foreach

    所以要可以foreach只需要对象定义了GetEnumerator无参方法,并且返回值是IEnumerator或其对应的泛型

    注意只有方法名和返回类型

    
                var ets = my.GetEnumerator();
                while(ets.MoveNext())
                {
                    Console.WriteLine(ets.Current);
                }
                 

    也就是说,只要可以满足上面这三步调用即可。不一定要继承于IEnumerable

    yield的使用

    你肯定发现了我们自己去实现IEnumerator接口还是有些许麻烦,并且上面的代码肯定是不够健壮。

    你会发现我们连MyIEnumerator都没要了,也可以正常运行。太神奇了。yield到底为我们做了什么呢?

    好家伙,我们之前写的那一大坨。你一个yield关键字就搞定了

    我们继续来看GetEnumerator的定义和调用

    我们调用GetEnumerator的时候,看似里面for循环了一次,其实这个时候没有做任何操作。只有调用MoveNext的时候才会对应调用for循环

    现在我想可以回答你“为什么Linq to Object中要返回IEnumerable?”:

    因为IEnumerable是延迟加载的,每次访问的时候才取值。也就是我们在Lambda里面写的where、select并没有循环遍历(只是在组装条件),只有在ToList或foreache的时候才真正去集合取值了。这样大大提高了性能。

    如:

    这个时候得到了就是IEnumerable对象,但是没有去任何遍历的操作。

    我们再来做个实验,自己实现MyWhere:

    执行到MyWhere的时候什么动作都没有(返回的就是IEnumerable),只有执行到ToList的时候才代码才真正的去遍历筛选。

    原文

  • 相关阅读:
    opengl中的Floatbuffer和IntBuffer与java中数据的存储方式不同的解决方法,编辑一个自己的BufferUtil工具类
    android程序与java程序的差别。
    android的json解析
    java数组转list,list转数组。
    java中字符串常量,堆栈的区别和字符串函数intern(),String s=new String(“abc”)中abc在内存的分配
    AsyncTask学习
    关于自定义拦截器配置,及拦截器的作用范围
    struts2中的文件上传和文件下载
    Struts2的配置及入门案例
    Action中动态方法的调用 Action中通配符的使用 Result的配置
  • 原文地址:https://www.cnblogs.com/wwkk/p/8285231.html
Copyright © 2011-2022 走看看