C#面试题更新 2026-08-03

请解释 C# 中 IEnumerable 与 IEnumerator 接口在职责和用法上的差异。

考察说明

考查对 C# 集合遍历核心接口模型的理解,以及二者协作而非对立的本质。

回答思路

  1. 【回答框架 1】IEnumerable 与 IEnumerator 是 C# 中实现集合遍历的一对协作接口。IEnumerable 的核心职责是定义一个可被迭代的集合,它只提供一个 GetEnumerator 方法,用于返回一个与当前集合关联的枚举器对象。而 IEnumerator 负责实际的迭代状态管理,它包含 Current 属性以及 MoveNext 和 Reset 方法,通过 MoveNext 推进游标并返回是否还有元素,Current 获取当前元素。
  2. 【回答框架 2】在用法上,foreach 语句的底层机制正是调用集合的 GetEnumerator 获得一个 IEnumerator,然后循环调用 MoveNext 并读取 Current,直到 MoveNext 返回 false。因此,IEnumerable 是集合面向使用者的门面,而 IEnumerator 则是迭代过程的执行者,二者通常联合使用,而不是彼此替代。
  3. 【回答框架 3】从设计角度看,IEnumerable 定义的是可枚举的抽象能力,IEnumerator 定义的是具体的枚举状态机。实现 IEnumerable 的类可以通过 yield return 语法让编译器自动生成一个 IEnumerator,从而简化自定义集合的迭代实现。这种分离使得同一个集合可以产生多个独立的枚举器,各枚举器维护自己的遍历位置,互不干扰。
  4. 【回答框架 4】实践中,遇到需要遍历集合的接口参数时通常使用 IEnumerable,而如果需要手动控制迭代过程或直接操作游标,则使用 IEnumerator。理解二者区别有助于正确设计集合类与迭代逻辑,也能避免混淆接口的职责边界。
  5. 【关键点 1】IEnumerable 提供 GetEnumerator 方法,声明集合可被遍历;IEnumerator 提供 Current、MoveNext 和 Reset,负责具体的遍历状态。
  6. 【关键点 2】foreach 的内部实现依赖 IEnumerator:先获取枚举器,再循环 MoveNext 与 Current。
  7. 【关键点 3】使用 yield return 可让编译器自动生成 IEnumerator,简化自定义迭代。
  8. 【关键点 4】同一集合上的多个枚举器相互独立,各自维护位置。
  9. 【关键点 5】接口协作关系:IEnumerable 面向集合消费者,IEnumerator 面向迭代执行者。
  10. 【易错点 1】不要将 IEnumerable 与 IEnumerator 视为功能对等的可选项,二者是职责分离的协作关系。
  11. 【易错点 2】Reset 方法在多数枚举器中可能不受支持或抛异常,不应依赖它重置遍历。
  12. 【易错点 3】实现 IEnumerable 时若手动编写 IEnumerator,需注意正确实现 MoveNext 和 Current 的状态推进,否则可能导致死循环或空遍历。