C#基础 —— IEnumerable 和 IEnumerator 的区别
目录
在 Unity 和 C# 开发中,IEnumerable 和 IEnumerator 是处理集合遍历的核心接口。简单来说:IEnumerable 是“可以被迭代的容器”,而 IEnumerator 是“执行迭代的游标”。
1. 核心定义与角色
IEnumerable (可枚举接口)
它是集合的声明。如果一个类实现了 IEnumerable,就意味着它承诺:“你可以用 foreach 来遍历我”。
- 主要方法:只包含一个方法
GetEnumerator(),返回一个IEnumerator对象。 - 类比:它就像一本书。书本身包含了所有内容,并告诉你:“你可以读我”。
IEnumerator (枚举器接口)
它是遍历过程中的状态机。它记录了当前遍历到了哪个位置。
- 主要成员:
Current: 获取当前指向的元素。MoveNext(): 将游标移向下一个元素,如果没有更多元素则返回false。Reset(): 将游标重置到初始位置(通常在第一个元素之前)。
- 类比:它就像书里的书签。它标记了你当前读到了哪一页,并能让你翻到下一页。
2. 关键区别对比
| 特性 | IEnumerable | IEnumerator |
|---|---|---|
| 职责 | 暴露一个枚举器。 | 控制集合的遍历逻辑(前进、获取当前值)。 |
| 主要方法/属性 | GetEnumerator() |
MoveNext(), Current, Reset() |
| 遍历方式 | 支持 foreach 语法。 |
需要手动调用 MoveNext() 和 Current。 |
| 状态记录 | 不记录遍历状态(它是无状态的)。 | 记录遍历位置(它是有状态的)。 |
| 常见用途 | 定义数组、列表、字典等集合。 | 实现 Unity 协程 (Coroutine) 或自定义迭代逻辑。 |
3. 代码示例
IEnumerable 的使用 (自动遍历)
当你使用 foreach 时,编译器在底层会自动为你调用 GetEnumerator()。
using System.Collections.Generic;
using UnityEngine;
public class Example : MonoBehaviour
{
void Start()
{
List<string> items = new List<string> { "Apple", "Banana", "Cherry" };
// 背后实际上是获取了 IEnumerator
foreach (var item in items)
{
Debug.Log(item);
}
}
}
IEnumerator 的使用 (手动遍历)
如果你想手动控制每一步,就需要直接操作 IEnumerator。
IEnumerator<string> enumerator = items.GetEnumerator();
while (enumerator.MoveNext()) // 尝试移向下一个
{
string currentItem = enumerator.Current; // 获取当前值
Debug.Log(currentItem);
}
4. 为什么 Unity 的协程使用 IEnumerator?
Unity 的协程系统利用了 IEnumerator 的状态保存能力。
当你在协程中使用 yield return 时,函数执行会暂停,并把当前的执行状态(局部变量和进度)保存在 IEnumerator 对象中。Unity 的引擎每帧都会检查这个枚举器,调用 MoveNext(),如果条件满足(比如时间到了),就继续执行下一行代码。
核心逻辑:
StartCoroutine接收一个IEnumerator(书签)。- Unity 引擎在每一帧(或指定时间)扮演“手”的角色,去翻动这个“书签”。

浙公网安备 33010602011771号