【C#】LINQ操作实现 IEnumerable<T> 接口的集合

IEnumerable<TSource> 接口详解

IEnumerable<TSource> 

IEnumerable<TSource> 是 C# 中的一个泛型接口,它定义了如何遍历一组对象。这个接口是.NET Framework 中 LINQ (Language Integrated Query) 的基础之一,用于提供一种统一的方式来访问不同类型的集合。


IEnumerable<TSource> 接口只有一个方法 GetEnumerator(),该方法返回一个实现了 IEnumerator<TSource> 接口的对象,也就是枚举器(enumerator)。枚举器是用来迭代集合中的每一个元素的工具。

 

GetEnumerator() 方法

GetEnumerator() 方法是 IEnumerable<TSource> 接口中定义的唯一方法,它的作用是返回一个 IEnumerator<TSource> 接口的实现。这个方法的主要目的是创建一个能够遍历集合中元素的对象。当一个类实现了 IEnumerable<TSource> 接口时,它必须提供一个 GetEnumerator() 方法,该方法返回一个能够遍历该类中元素的枚举器。

GetEnumerator() 方法何时被调用

GetEnumerator() 方法通常不会由程序员直接调用,而是由 C# 的语言构造(如 foreach 循环)自动调用。例如当使用foreach循环遍历某个实现了IEnumerable<TSource> 的集合时,编译器会在 foreach 循环内部自动调用 GetEnumerator() 方法来获取一个枚举器(IEnumerator<T> 实例),然后使用这个枚举器来迭代集合中的每一个元素。这个枚举器就是实现了 IEnumerator<T> 接口的对象。

IEnumerator<TSource> 接口

IEnumerator<TSource> 是一个枚举器接口,它定义了如何在集合中前进以及如何访问当前项。IEnumerator<TSource> 包含以下三个核心方法:

  • Current 属性:获取当前元素。
  • MoveNext() 方法:将枚举器移动到序列中的下一个元素,并返回一个布尔值指示是否还有更多的元素。
  • Reset() 方法:将枚举器重置到序列的开始。

枚举器方法的使用时机

  • Current 属性:在每次成功调用 MoveNext() 后,可以访问当前元素。对于 foreach 循环,编译器会自动处理这一部分。
  • MoveNext() 方法:当需要从一个元素移动到下一个元素时调用。例如,在 foreach 循环内部,编译器会自动调用此方法来移动到下一个元素。如果 MoveNext() 返回 true,则表示还有更多的元素可供迭代;如果返回 false,则表示已经到达了集合的末尾。
  • Reset() 方法:用于将枚举器重置到序列的开始。这个方法在实际编程中并不常用,因为 foreach 循环通常会自己管理枚举器的状态,不过它在某些情况下(比如手动控制枚举器)可能是有用的。

 

IEnumerable<TSource> 的用途

IEnumerable<TSource> 主要有以下几个用途:

  • 集合遍历:通过实现 IEnumerable<TSource>,一个类就可以被 foreach 循环或其他 LINQ 查询所遍历。
  • 延迟执行:IEnumerable<TSource> 支持惰性加载,即在需要的时候才计算或获取数据。这对于处理大量数据或从数据库读取数据非常有用。
  • 统一的查询模型:通过 LINQ,你可以使用相同的查询语法来操作任何实现了 IEnumerable<TSource> 的集合,无论是内存中的数组还是数据库表。
  • 链式调用:可以对实现了 IEnumerable<TSource> 的对象进行方法链式调用,如 .Where().Select().OrderBy() 等 LINQ 方法。

总之,IEnumerable<TSource> 提供了一个标准的方式来访问集合中的元素,使得不同的数据源可以以一致的方式被访问和操作。

实现了 IEnumerable<T> 的数据结构

  • List<T>: 一个动态数组,提供了快速随机访问和插入操作。
  • Array: 固定大小的数组,支持快速的随机访问。
  • LinkedList<T>: 双向链表,适合频繁插入和删除操作。
  • Stack<T>: 栈是一种后进先出(LIFO)的数据结构。
  • Queue<T>: 队列是一种先进先出(FIFO)的数据结构。
  • HashSet<T>: 不重复元素的集合,支持快速查找。
  • Dictionary<TKey, TValue>: 键值对的集合,提供了键到值的映射。
  • SortedSet<T>: 排序的集合,不允许重复的元素。
  • SortedDictionary<TKey, TValue>: 排序的字典,不允许重复的键。
  • ObservableCollection<T>: 类似于 List<T>,但是提供了通知更改的功能。

 

 

LINQ操作实现 IEnumerable<T> 接口的集合

LINQ(Language Integrated Query)是一个框架,它提供了编写结构化查询的能力,并且能够应用于任何实现了 IEnumerable<T> 接口的数据源。这意味着 LINQ 不关心底层集合的具体实现,只要集合支持迭代(即实现了 IEnumerable<T> 接口),就可以使用 LINQ 对其进行查询。

LINQ 的灵活性在于它的查询表达式可以在任何数据源上运行,无论是内存中的集合、数据库表还是XML文档。这是因为 LINQ 查询通常由一系列标准查询运算符组成,这些运算符定义在 System.Linq.Enumerable 类中,并且可以应用于任何 IEnumerable<T>。

具体来说,System.Linq.Enumerable 类提供了大量的静态方法,这些方法可以作用于任何实现了 IEnumerable<T> 接口的对象上。例如,First(), FirstOrDefault(), Any() 等方法,它们都是扩展方法(extension methods),这意味着如果您有一个实现了 IEnumerable<T> 的对象,您可以像调用实例方法一样调用这些方法,但实际上它们是在 System.Linq.Enumerable 类中定义的静态方法。

例如,您可以对数组、列表、哈希表等任何实现了 IEnumerable<T> 接口的数据结构使用 LINQ 查询。这就意味着 LINQ 不仅仅局限于某些特定的数据结构如 List<T> 或 Array,而是可以广泛应用于各种不同的数据源。

 

 

posted @ 2024-09-11 15:11  ban_boi  阅读(14)  评论(0编辑  收藏  举报