C# 中的 IEnumerable 与 IQueryable2024 年 8 月 29 日 | 阅读 12 分钟 在 C# 中,IEnumerable 和 IQueryable 都是在 LINQ (Language Integrated Query) 中用于处理数据集合的接口,但它们的功能和特性有所不同。 什么是 IEnumerable?IEnumerable 是一个基本接口,它表示一个数据的前向光标。它用于查询和操作内存中的集合,例如数组、列表以及实现此接口的其他数据结构。 IEnumerable 是 System.Collection 命名空间的一部分,用于表示一组可枚举(迭代)的对象集合。它是处理集合的基本接口,提供了一种标准的方法来迭代集合中的元素,而无需暴露底层数据结构。 立即执行: 对 IEnumerable 序列执行的操作会立即生效。当你在 IEnumerable 上执行 LINQ 操作时,数据会在内存中被查询和处理,结果会作为新的序列或集合返回。 无延迟执行: 操作不是延迟的;它们在你调用 LINQ 方法(例如 Where、Select、ToList、ToArray 等)时立即执行。 适用于内存中集合: 它非常适合处理内存中的数据集合,因为整个数据集都可以装入内存。 LINQ to Objects: 它主要用于 LINQ to Objects,这意味着它处理的是已经加载到内存中的集合。 一定程度的强类型
示例特性它具有 C# 中 IEnumerable 的几个特性。 IEnumerable 的一些主要特性如下: 集合无关性 IEnumerable 是一种以通用、集合无关的方式与对象集合交互的方式。无论你处理的是数组、列表还是自定义集合,只要它实现了 IEnumerable,你都可以使用一组一致的方法来处理它。 迭代抽象 IEnumerable 提供了一种迭代抽象,而不是直接操作集合的底层数据结构。它允许你向集合请求一个枚举器 (IEnumerator),该枚举器知道如何遍历元素。 foreach 循环兼容性 IEnumerable 的一个关键优势在于它能够使用 foreach 循环轻松遍历集合中的元素。此循环依赖 GetEnumerator 方法获取枚举器,然后使用该枚举器遍历元素,而无需了解特定的集合类型。 LINQ 集成 IEnumerable 与 LINQ 紧密集成,LINQ 是 C# 中用于处理集合的强大查询语言。实现 IEnumerable 的集合可以利用 LINQ 丰富的扩展方法集来执行过滤、排序和投影等操作。 自定义迭代 你可以通过实现 IEnumerable 来使自己的类可迭代。当你有一个自定义集合并希望启用标准的迭代模式时,这很有帮助。实现 IEnumerable 意味着你需要提供一个枚举器,该枚举器定义了如何遍历集合中的元素。 基本 LINQ 支持
有限的查询优化
程序让我们用一个例子来说明 C# 中的 iEnumerable。 输出 Name: Alice, Age: 30 Name: Bob, Age: 25 Name: Charlie, Age: 35 说明
复杂度分析时间复杂度 将 Person 添加到 PeopleCollection:O(1) 将 Person 添加到 PeopleCollection 时,它会直接将其追加到内部列表中。这是一个 O(1) 操作,因为它不依赖于集合的大小。 使用 foreach 遍历 PeopleCollection:O(n) 当你使用 foreach 循环遍历 PeopleCollection 时,它本质上涉及遍历集合中的每个元素。时间复杂度为 O(n),其中 'n' 是集合中 Person 对象的数量。 空间复杂度 PeopleCollection 的空间复杂度:O(n) PeopleCollection 类内部使用 List 来存储 Person 对象。空间复杂度为 O(n),其中 'n' 是集合中存储的 Person 对象的数量。 Person 对象空间复杂度:每个 Person 对象 O(1) 每个 Person 对象都有为 Name 和 Age 属性分配的固定内存量。因此,每个 Person 对象的空间复杂度为 O(1)。 总而言之,将 Person 添加到集合的时间复杂度为 O(1),遍历集合的时间复杂度为 O(n)。PeopleCollection 类的空间复杂度为 O(n),每个 Person 对象的空间复杂度为 O(1)。 什么是 IQueryable?IQueryable 是一个扩展了 IEnumerable 的接口,专为从支持查询的数据源(如数据库)查询数据而设计。它是 LINQ to SQL、LINQ to Entities 以及其他 LINQ 提供程序的一部分。 延迟执行 IQueryable 允许你创建不会在构造时立即执行的查询。相反,只有当你显式请求结果时,它们才会被执行。 这种延迟执行是一项基本功能,因为它允许查询优化并最大限度地减少从数据源传输的数据量。 查询优化: 它允许进行查询优化,这意味着查询提供程序在处理数据库时可以将 LINQ 查询转换为高效的 SQL(或等效)查询。 适用于远程数据源: 它非常适合处理可以处理查询操作的数据源,如数据库。查询在远程数据源上执行,从而减少传输的数据量。 LINQ to SQL、LINQ to Entities: 它主要用于 LINQ to SQL、LINQ to Entities 或其他 LINQ 提供程序,你可以在其中处理存储在数据库或远程服务中的数据。 示例特性它具有 C# 中 IQueryable 的几个特性。IQueryable 的一些主要特性如下: 与数据源集成
类型安全
查询组合
表达式树
自定义查询提供程序
外部数据源集成
异步支持
程序让我们用一个例子来说明 C# 中的 IQueryable。 输出 People over 30: Charlie, 35 years old Names of all people: Alice Bob Charlie David Eve Sum of ages: 140 years 说明Person 类 我们定义了一个简单的 Person 类,包含 Name 和 Age 两个属性,用于表示个体。这个类将用于创建保存与人员相关数据的对象。 People 列表 我们创建了一个名为 people 的列表,并用 Person 类的实例填充它。这个列表代表了一个人集合,每个人都有一个名字和一个年龄。 IQueryable 创建 我们通过使用 AsQueryable 方法将 people 列表转换为 IQueryable。此转换允许我们对列表使用 LINQ 运算符,将其视为可查询的数据源。 查询操作 我们对 IQueryable 对象执行各种查询操作: 过滤 (Where): 我们创建了一个名为 over 30 的 IQueryable,它代表了一个查找年龄大于 30 的人的查询。 投影 (Select): 我们创建了一个名为 names 的 IQueryable,它代表了一个提取所有人名字的查询。 聚合 (Sum): 我们使用 Sum 运算符计算年龄总和,结果是一个名为 ageSum 的 int。 结果执行 我们通过迭代结果来显式执行查询。这时查询会被执行,数据被检索。
复杂度分析时间复杂度 创建和填充 people 列表 时间复杂度:O(n) 用 n 个项填充列表需要线性时间,因为每个人是逐个添加到列表中的。 从 people 创建 IQueryable 时间复杂度:O(1) 使用 AsQueryable 将 people 列表转换为 IQueryable 是一个常数时间操作,不依赖于列表的大小。 查询操作 (Where, Select, Sum) 时间复杂度:O(n) 使用 LINQ 执行查询操作,例如 Where、Select 和 Sum,通常需要对整个数据源进行一次遍历。这些操作的时间复杂度与数据源的大小成线性关系。 遍历结果 时间复杂度:O(n) 遍历查询操作的结果也需要线性时间,因为它需要访问结果集中的每个项。 空间复杂度 people 列表:O(n) people 列表的空间复杂度与存储在列表中的人数成线性关系。每个 Person 对象占用固定的内存量。 IQueryable 和查询运算符:O(1) 创建 IQueryable 和定义查询运算符不会显著增加内存使用量。使用的空间是常数,不依赖于数据源的大小。 查询结果 (over30, names, ageSum):O(m) 查询结果(over30、names 和 ageSum)的空间复杂度取决于结果集的大小。如果结果集包含 m 项,则空间复杂度为 O(m)。 空间复杂度取决于结果集的大小和原始 people 列表,列表的空间复杂度为 O(n),查询结果的空间复杂度为 O(m),其中 "n" 是列表中的人数,"m" 是每个查询中的结果数。 IEnumerable 和 IQueryable 的主要区别IEnumerable 和 IQueryable 之间存在几个区别。IEnumerable 和 IQueryable 之间的一些主要区别如下: 目的IEnumerable
IQueryable
立即执行与延迟执行IEnumerable
IQueryable
数据源IEnumerable
IQueryable
强类型IEnumerable
IQueryable
优化IEnumerable
IQueryable
与 LINQ 集成IEnumerable
IQueryable
自定义数据源IEnumerable
IQueryable
结论总而言之,IEnumerable 最适合内存中的集合和操作的即时执行,而 IQueryable 则专为具有延迟执行和查询优化的外部数据源的查询而设计。选择哪一个取决于你的数据性质和应用程序的具体需求。 |
我们请求您订阅我们的新闻通讯以获取最新更新。