C# 中IEnumerable与IQuerable的区别

news2024/11/14 20:40:57

目的

详细理清IEnumerator、IEnumerable、IQuerable三个接口之间的联系与区别

继承关系:IEnumerator->IEnumerable->IQuerable

IEnumerator:枚举器

包含了枚举器含有的方法,谁实现了IEnuemerator接口中的方法,就可以自定义成为一个枚举器。

 public interface IEnumerator
    {
        [__DynamicallyInvokable]
        object Current
        {
            [__DynamicallyInvokable]
            get;
        }

        [__DynamicallyInvokable]
        bool MoveNext();

        [__DynamicallyInvokable]
        void Reset();
    }

实现了IEnumerator接口,就可以获得Current、MoveNext、以及Reset方法,可以实现迭代遍历等操作。
1.Current 返回序列中当前位置项的属性
2.MoveNext 把枚举器位置前进到集合的下一项中
3.Reset 把位置重置为原始状态的方法

public interface IEnumerable
    {
        [DispId(-4)]
        [__DynamicallyInvokable]
        IEnumerator GetEnumerator();
    }

在这里插入图片描述

IEnumerator就是一个枚举器,包含的方法可以遍历元素。IEnumerable、IQuerable接口中都含有可以获取IEnumerator这个枚举器的GetEnumerator()方法,通过实现GetEnumerator方法来返回对象的枚举器。

IEnumerable接口:获取IEnumerator枚举器

IEnumerable是.NET Framework中的一个基础接口,用于遍历集合中的元素。它提供了一种通用的数据遍历方法,不依赖于数据的具体类型或结构。实现了IEnumerable接口的类或集合可以使用foreach语句进行遍历。枚举器提供了对集合中元素的逐个访问,以此来实现对集合的迭代。 使用 IEnumerable 接口可以使你的集合类通过 foreach 循环来遍历。foreach 循环会自动调用集合的 GetEnumerator() 方法,然后使用枚举器来逐个访问集合中的元素。

实现了IEnumerable接口的类是可枚举类,IEnumerable只有一个成员-GetEnumerator 方法,返回一个对象的枚举器。
在这里插入图片描述

IQuerable接口:同样获取IEnuerator枚举器

IQueryable接口继承自IEnumerable,并为其添加了查询功能。IQueryable主要用于LINQ(Language Integrated Query)查询,它允许开发者使用类似于SQL的语法来查询和操作数据。与IEnumerable不同,IQueryable的查询是可以被优化的,因为它允许查询提供程序在查询执行前分析和优化查询表达式。

IEnumerable与IQuerable接口区别

这两个接口都是用于枚举一系列的元素,但它们的工作方式和应用场景有很大的不同,主要体现在它们如何处理查询和数据访问。

IEnumerable

  • 定义IEnumerable<T>是一个在.NET Framework中用于表示可枚举对象的泛型接口。它定义了一个方法GetEnumerator(),该方法返回一个IEnumerator<T>对象,用于遍历集合中的元素。
  • 使用场景:通常用于内存中的集合,如List、Array等。
  • 扩展方法:LINQ to Objects扩展方法(如SelectWhere等)在IEnumerable<T>上操作,它们接受委托(如Func<T, TResult>)作为参数,直接在内存中的集合上执行操作。
  • 性能:因为这些操作是在内存中直接执行的,所以它们的执行速度通常很快,但可能会受到内存大小和集合大小的限制。

IQueryable

  • 定义IQueryable<T>IEnumerable<T>的扩展,用于支持查询功能。它定义了ExpressionElementType属性,以及ProviderExecute方法。IQueryable<T>通常用于支持查询提供者的集合,如数据库或XML数据源。
  • 使用场景:主要用于数据源查询,如数据库查询,允许延迟执行和查询优化。
  • 扩展方法:虽然IQueryable<T>也支持类似SelectWhere等LINQ扩展方法,但这些方法接受的是Expression<Func<T, TResult>>(或类似的表达式类型)作为参数,而不是简单的Func<T, TResult>。这些表达式被转换成表达式树(Expression Trees),然后可以由查询提供者(如LINQ to SQL或Entity Framework)转换成特定于数据源的查询语言(如SQL)。
  • 性能:因为查询被转换为针对数据源优化的形式(如SQL查询),所以这些查询可能在执行时更加高效,尤其是在处理大量数据时。然而,构建和执行这些查询可能会比直接在内存中处理数据要慢一些。

IEnumerable

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);  
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate); 

IQuerable

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);  
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, int, bool>> predicate);  

在这两个接口的扩展方法中,一个传入的是Func委托,另一个传入的是包装了Func委托的表达式树,表达式树会对查询进行优化,而不是会像前者直接加载到内存中,在进行查询等操作。所以提升了查询效率。

执行时机与性能
IEnumerable:当遍历IEnumerable集合时,数据会被立即加载到内存中,并且查询操作在内存中进行,处理大量数据,可能会消耗大量的内存资源,此外,IEnumerable的查询操作通常不会被优化。
IQuerable:与IEnumerable不同,IQueryable的查询操作是在查询执行时才进行的,而不是在定义查询时。这使得IQueryable能够支持延迟执行(deferred execution)和查询优化。对于大型数据集或远程数据源(如数据库),这种特性可以显著提高性能。

使用场景
IEnumerable
适用于内存中的数据集合,如数组、列表等。当数据量不大,或者需要立即执行查询操作时,使用IEnumerable是合适的。
IQuerable
适用于可以优化的远程数据源,如数据库、Web服务等。当处理大量数据或需要延迟执行查询时,使用IQueryable更为高效。

总结

主要区别在于IQueryable<T>支持将LINQ查询转换为针对数据源优化的查询(如SQL查询),而IEnumerable<T>则在内存中直接操作集合。这种差异导致了在IQueryable<T>的扩展方法中使用Expression<Func<T, TResult>>而不是Func<T, TResult>,因为表达式树可以被查询提供者转换为特定于数据源的查询语言。IEnumerable适用于内存中的数据集合,而IQueryable则更适用于可以优化的远程数据源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1932314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【坑】微信小程序开发wx.uploadFile和wx.request的返回值格式不同

微信小程序 使用wx.request&#xff0c;返回值是json&#xff0c;如下 {code:200,msg:"更新用户基本信息成功",data:[]} 因此可以直接使用如 res.data.code获取到返回值中的code字段 但是&#xff0c;上传图片需要使用wx.uploadFile&#xff0c;返回的结果如下 …

【知识图谱】【红楼梦】

参考链接 安装、使用教程&#xff08;知乎&#xff09;&#xff1a;https://zhuanlan.zhihu.com/p/634006024Git &#xff1a;https://github.com/chizhu/KGQA_HLM 注&#xff1a;原项目为 【 重庆邮电大学&#xff0c;2018 林智敏 的毕业设计 】。【 感谢大佬的分享 】。 jav…

Web渗透:Shiro550漏洞(CVE-2016-4437)

Apache Shiro 是一个强大且易于使用的Java安全框架&#xff0c;提供了身份验证&#xff08;Authentication&#xff09;、授权&#xff08;Authorization&#xff09;、会话管理&#xff08;Session Management&#xff09;和密码学支持等功能。Apache Shiro 550反序列化漏洞&a…

set类和map类介绍和简单使用

目录 set类介绍与简单使用 set类 multiset类 map类介绍与简单使用 map类 multimap类 set类介绍与简单使用 set类是一种关联式容器&#xff0c;在数据检索时比序列式容器效率更高。本质是一个常规的二叉搜索树&#xff0c;但是为了防止出现单支树导致效率下降进行了相关优…

188数码管轮询扫描

前言 最近用到了188数码管&#xff0c;总结一下。 188数码管&#xff0c;用5个IO&#xff0c;在不借助外部驱动芯片的情况下&#xff0c;可以点亮20个灯。188数码管广泛应用于电子烟、充电器、充电宝、DVD、高级音响、工业设备控制面板、医疗器械等多个领域&#xff0c;满足不…

FPGA FIR fdatool filter designer MATLAB

位数问题 fdatool 先确定输入信号的位宽&#xff0c;比如17位在fdatool中&#xff0c;选set quantization parameters 选input/output 设置input word length 为17bit(not confirmed) fir compiler implementation 注意&#xff1a; 当设置输入位宽为16位时&#xff0c;ip核…

Java 快速入门学习 -- Day 2

Java 快速入门 Ⅱ maven&#xff08;图书管理员&#xff09;IDEA使用 maven框架 maven&#xff08;图书管理员&#xff09; maven 仓库&#xff0c;图书馆。要看书的化先从家里找&#xff08;本地仓库&#xff09;&#xff0c;本地找不到就去中央仓库或者镜像仓库找&#xff0c…

CSA笔记3-文件管理命令(补充)+vim+打包解包压缩解压缩命令

grep(-i -n -v -w) [rootxxx ~]# grep root anaconda-ks.cfg #匹配关键字所在的行 [rootxxx ~]# grep -i root anaconda-ks.cfg #-i 忽略大小写 [rootxxx ~]# grep -n root anaconda-ks.cfg #显示匹配到的行号 [rootxxx ~]# grep -v root anaconda-ks.cfg #-v 不匹配有…

记录些MySQL题集(8)

ACID原则、事务隔离级别及事务机制原理 一、事务的ACID原则 什么是事务呢&#xff1f;事务通常是由一个或一组SQL组成的&#xff0c;组成一个事务的SQL一般都是一个业务操作&#xff0c;例如聊到的下单&#xff1a;「扣库存数量、增加订单详情记录、插入物流信息」&#xff0…

AQS详解

文章目录 AQS 是什么&#xff1f;AQS 的原理是什么&#xff1f;AQS 资源共享方式总结 AQS 是什么&#xff1f; AQS 的全称为 AbstractQueuedSynchronizer &#xff0c;翻译过来的意思就是抽象队列同步器。这个类在 java.util.concurrent.locks 包下面。 AQS是一个用来构建锁和…

【操作系统】定时器(Timer)的实现

这里写目录标题 定时器一、定时器是什么二、标准库中的定时器三、实现定时器 定时器 一、定时器是什么 定时器也是软件开发中的⼀个重要组件.类似于⼀个"闹钟".达到⼀个设定的时间之后,就执行某个指定 好的代码. 定时器是⼀种实际开发中⾮常常用的组件. ⽐如⽹络通…

base SAS programming学习笔记13(Array)

1.Array array-name{dimension} <elements> array-name&#xff1a;向量名称 dimension&#xff1a;向量长度&#xff0c;默认为1&#xff1b; elements:列出变量名&#xff0c;变量名要么全是数值变量或者全是字符变量 array-name和variable不能相同&#xff1b;也不能和…

【BUG】已解决:java.lang.IllegalStateException: Duplicate key

已解决&#xff1a;java.lang.IllegalStateException: Duplicate key 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市…

Java红娘婚恋相亲交友系统小程序源码

红娘婚恋相亲交友小程序&#xff1a;遇见爱情&#xff0c;从指尖开始&#x1f496; &#x1f4f1; 掌中红娘&#xff0c;随时待命 &#x1f48c; 在这个数字化时代&#xff0c;爱情也迎来了它的新舞台——“红娘婚恋相亲交友小程序”。只需轻轻一点&#xff0c;你的专属红娘就…

记录些MySQL题集(6)

MySQL 单表为什么不要超过 2000W 行&#xff1f; 数据持久化在磁盘中&#xff0c;磁盘的最小单元是扇区&#xff0c;一个扇区 0.5 KB&#xff0c;而由 8 个扇区可以构成一个文件系统块&#xff08;4K&#xff09;&#xff0c;以 InnoDB 存储引擎为例&#xff0c;一个数据页的大…

浅谈C嘎嘎类与对象

本篇文章与大家浅谈一下C嘎嘎的类与对象知识点 类的定义 关键字&#xff1a;class 语法格式&#xff1a; class 类名 { }&#xff1b;//这里的分号不能少 此外&#xff0c;class有三个属性分别是private、public、protected&#xff0c;这三个属性是干啥的&#xff0c;相…

昇思25天学习打卡营第13天|CycleGAN 图像风格迁移互换全流程解析

目录 数据集下载和加载 可视化 构建生成器 构建判别器 优化器和损失函数 前向计算 计算梯度和反向传播 模型训练 模型推理 数据集下载和加载 使用 download 接口下载数据集&#xff0c;并将下载后的数据集自动解压到当前目录下。数据下载之前需要使用 pip install dow…

如何PR到别人仓库(指定分支,无废话)

如何PR到别人仓库&#xff08;指定分支&#xff09; 记录一下&#xff0c;之前都是直接master分支&#xff0c;现在记录如何pr到别人仓库的其他分支 首先进入别人仓库然后点击fork到自己仓库 步骤&#xff08;以博主自己一个例子为例&#xff09; &#xff08;1&#xff09;…

配置和保护SSH

使用SSH访问远程命令行 描述Secure Shell SSH&#xff08;Secure Shell&#xff09; 是一种网络协议&#xff0c;用于在不安全的网络上安全地进行系统管理和数据传输。它最初由 Tatu Ylnen 于1995年设计&#xff0c;并成为保护网络服务免受攻击的标准。SSH提供了多种功能&…

prometheus+grafana应用监控配置

配置Prometheus 官方地址&#xff1a;Download | Prometheus &#xff08;wegt下载压缩包&#xff0c;解压并重命名prometheus&#xff0c;文件放于/data/prometheus即可&#xff09; 配置 service方法(文件放于 /etc/systemd/system/prometheus.service)&#xff1a; [Unit…