IEnumerable<T> 是 .NET 中最核心的接口之一,位于 System.Collections.Generic 命名空间中。它代表一个可枚举的集合,支持在集合上进行迭代操作。
IEnumerable<T> 是什么?
public interface IEnumerable<out T> : IEnumerable{ IEnumerator<T> GetEnumerator();
}它定义了一个可枚举对象的契约;
任何实现了
IEnumerable<T>的类型都能被foreach循环遍历;泛型版
IEnumerable<T>是非泛型IEnumerable的类型安全扩展;它的核心方法只有一个:
GetEnumerator()。
IEnumerable 与 IEnumerator 的关系
要理解 IEnumerable<T>,必须知道它依赖另一个接口:
public interface IEnumerator<out T> : IDisposable, IEnumerator{
T Current { get; } bool MoveNext(); void Reset(); // 通常不实现}关系示意图:
IEnumerable<T> └── GetEnumerator() └── 返回 IEnumerator<T> ├── MoveNext() → 是否还有元素 ├── Current → 当前元素 └── Reset() → 重置(可选)
基本用法
using System;using System.Collections.Generic;class Program{ static void Main()
{
List<string> fruits = new List<string> { "Apple", "Banana", "Cherry" };
// 使用 foreach 遍历(推荐)
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
// 等价的手动迭代方式
IEnumerator<string> enumerator = fruits.GetEnumerator(); try
{ while (enumerator.MoveNext())
{ string fruit = enumerator.Current;
Console.WriteLine(fruit);
}
} finally
{
enumerator?.Dispose();
}
}
}手写一个 IEnumerable<T> 示例
public class NumberCollection : IEnumerable<int>
{ private readonly int[] _numbers = { 1, 2, 3, 4, 5 }; public IEnumerator<int> GetEnumerator()
{ foreach (var n in _numbers) yield return n;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}使用:
var numbers = new NumberCollection();foreach (var n in numbers)
{
Console.WriteLine(n);
}输出:
1 2 3 4 5
yield return 的魔法
等价于下面的展开版:
public IEnumerator<int> GetEnumerator(){ return new Enumerator();
}private class Enumerator : IEnumerator<int>
{ private int _index = -1; private readonly int[] _numbers = { 1, 2, 3, 4, 5 }; public int Current => _numbers[_index]; object IEnumerator.Current => Current; public bool MoveNext()
{
_index++; return _index < _numbers.Length;
} public void Reset() => _index = -1; public void Dispose() { }
}yield 编译后自动生成状态机类,就是这种效果。