欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

浅谈IEnumerator、IEnumerable、IQueryable

程序员文章站 2022-04-24 11:11:57
...

IEnumerator是所有枚举数的基接口,继承此接口的类型通过实现MoveNext,Current,Reset方法实现迭代器。
IEnumerable是任何Collection集合实现foreach遍历都要继承的接口(主要是实现其中返回类型为IEnumerator的GetEnumerator方法)
IQueryable和IEnumerable都具有延迟加载的功能,IEnumerable主要运用于本地数据集,常用于Linq to object,而IQuerable多用于远程数据集,常用于Linq to Sql。
下面动手实现不继承IEnumerable而支持实现foreach的类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ForeachDemo
{
    public class PersonEnumerable
    {
        private string[] strList;
        public PersonEnumerable(string[] _strList)
        {
            strList = _strList;
        }
        public IEnumerator GetEnumerator()
        {
            //return new Person(strList);
            for (int i = 0; i < strList.Length; i++)
            {
                yield return strList[i];
            }
        }
    }
}

main方法

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ForeachDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] person = {"wen","jin","lei" };
            PersonEnumerable personEnumable = new PersonEnumerable(person);

foreach (var item in personEnumable)
{
    Console.WriteLine(item);
}

Console.ReadLine();
       }
    }
}

这里其实是用了yield关键字来实现了IEnumerator的Current、MoveNext、Reset方法,可以用ILSPY查看反编译后的代码,所以说要想一个类可通过foreach实现遍历,并不一定要继承IEnumerable接口,只要实现GetEnumerator()方法就好。

再来说说IEnumerable和IQueryable的区别

public void LinqTest()  
03.       {  
04.           var db = new SecurityRepositoryContext(new HSLogger());  
05.           var ur = new UserRepository(db);  
07.           IQueryable<User> querys = (from c in db.Context.Set<User>()  
08.                                      orderby c.Code  
09.                                      select c).Skip<User>(2).Take<User>(2);  
10.           //注意这个AsEnumerable<User>()在分页查询之前,先将其转换成IEnumerable类型  
11.           IEnumerable<User> enumers = (from c in db.Context.Set<User>()  
12.                                        orderby c.Code  
13.                                        select c).AsEnumerable<User>().Skip<User>(2).Take<User>(2);  
14.           //因为启用了延迟加载机制,所以下面调用一下,才会真正去读取数据库  
15.           foreach (var c in querys)  
16.           {  
17.               //TODO  
18.           }  
19.           foreach (var c in enumers)  
20.           {   
21.               //TODO  
22.           }  
23.       }  

类型为IQueryable 的querys 实际上并没有去数据库取值,而是在执行foreach时,才会把skip和take编译成sql中的条件去数据库中取值,这样的好处是不用把所有的结果集都加载到内存中后再去筛选符合条件的数据。

类型为IEnumerable的enumers 同样也是在做foreach时去数据库取值,不同的是,它是将所有的数据全部加载到内存后再去通过委托去筛选符合条件的数据。
继承了IQueryable的类实现的扩展方法如Where、select等接受的参数都是表达式树,而IEnumerable接受的是委托

相关标签: 枚举类型

上一篇: Java知识点

下一篇: Java 知识点