C#基础 —— IEnumerable 和 IEnumerator 的区别

在 Unity 和 C# 开发中,IEnumerableIEnumerator 是处理集合遍历的核心接口。简单来说: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(),如果条件满足(比如时间到了),就继续执行下一行代码。

核心逻辑

  1. StartCoroutine 接收一个 IEnumerator(书签)。
  2. Unity 引擎在每一帧(或指定时间)扮演“手”的角色,去翻动这个“书签”。
posted @ 2026-04-16 17:55  Reed_Chill  阅读(65)  评论(0)    收藏  举报