当前位置:首页 > C# > 正文

掌握C#自定义枚举器(从零开始构建IEnumerable与IEnumerator实现)

在C#编程中,C#自定义枚举器是实现集合类可遍历能力的关键技术。通过自定义枚举器,你可以控制对象如何被 foreach 循环遍历,从而提供更灵活、高效的数据访问方式。本教程将手把手教你如何从零开始创建自己的 IEnumerableIEnumerator 实现,即使你是编程小白也能轻松上手。

掌握C#自定义枚举器(从零开始构建IEnumerable与IEnumerator实现) C#自定义枚举器  IEnumerable接口 IEnumerator接口 C#迭代器教程 第1张

什么是枚举器?

在C#中,枚举器(Enumerator)是一种允许你逐个访问集合中元素的对象。当你使用 foreach 遍历一个集合(如 List、Array 等)时,背后其实是在调用该集合的枚举器。

要支持 foreach,一个类必须实现 IEnumerable 接口(或 IEnumerable<T> 泛型接口),而 IEnumerable 接口要求你提供一个返回 IEnumerator 对象的方法。

核心接口介绍

  • IEnumerable:包含一个方法 GetEnumerator(),用于返回一个枚举器对象。
  • IEnumerator:包含三个成员:Current(当前元素)、MoveNext()(移动到下一个元素)、Reset()(重置位置)。

现代C#开发中,我们通常使用泛型版本:IEnumerable<T>IEnumerator<T>,它们类型安全且无需强制转换。

实战:创建一个简单的自定义集合

假设我们要创建一个只能存储整数的简单集合 MyIntCollection,并让它支持 foreach 遍历。

步骤1:实现 IEnumerator<int>

public class MyIntEnumerator : IEnumerator<int>{    private readonly int[] _data;    private int _position = -1; // 初始位置在第一个元素之前    public MyIntEnumerator(int[] data)    {        _data = data;    }    public int Current    {        get        {            if (_position < 0 || _position >= _data.Length)                throw new InvalidOperationException();            return _data[_position];        }    }    object IEnumerator.Current => Current;    public bool MoveNext()    {        _position++;        return _position < _data.Length;    }    public void Reset()    {        _position = -1;    }    public void Dispose()    {        // 如果有非托管资源需要释放,可以在这里处理        // 本例中无需操作    }}

步骤2:实现 IEnumerable<int>

public class MyIntCollection : IEnumerable<int>{    private readonly int[] _items;    public MyIntCollection(params int[] items)    {        _items = items ?? new int[0];    }    public IEnumerator<int> GetEnumerator()    {        return new MyIntEnumerator(_items);    }    IEnumerator IEnumerable.GetEnumerator()    {        return GetEnumerator();    }}

步骤3:测试你的自定义枚举器

class Program{    static void Main()    {        var collection = new MyIntCollection(10, 20, 30, 40);        foreach (int number in collection)        {            Console.WriteLine(number);        }        // 输出:        // 10        // 20        // 30        // 40    }}

更简单的方式:使用 yield return

虽然手动实现 IEnumerableIEnumerator 能让你完全掌控遍历逻辑,但C#提供了更简洁的语法糖:yield return。它能自动为你生成枚举器代码。

public class SimpleCollection : IEnumerable<int>{    private readonly int[] _items;    public SimpleCollection(params int[] items)    {        _items = items;    }    public IEnumerator<int> GetEnumerator()    {        foreach (var item in _items)        {            yield return item;        }    }    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();}

使用 yield return 不仅代码更短,而且编译器会自动生成状态机来管理枚举过程,非常适合大多数场景。但在需要精细控制(如并发访问、复杂状态管理)时,手动实现 C#迭代器教程 中提到的完整枚举器仍是必要选择。

总结

通过本教程,你已经学会了如何开发 C#自定义枚举器,理解了 IEnumerable 接口和 IEnumerator 接口的核心作用,并掌握了两种实现方式:手动编写和使用 yield return。这些知识是深入理解C#集合框架和LINQ的基础。

记住,良好的枚举器设计不仅能提升代码可读性,还能优化内存使用和性能。继续练习,尝试为字符串列表、自定义对象等创建枚举器,巩固你的 C#迭代器教程 所学内容!