首先是foreach的实际工作:
foreach (var item in humanList)
{
Console.WriteLine(item.ToString());
}
#region 实际工作
IEnumerator<Human> enumerator = humanList.GetEnumerator();
while (enumerator.MoveNext())
{
Human item = enumerator.Current;
Console.WriteLine(item.ToString());
}
IDisposable disposable = enumerator as IDisposable;
if (disposable != null) disposable.Dispose();
#endregion
应该不难看懂(看不懂结合下文),IEnumerable<T>
被集合中的几乎所有类和接口所继承,可以理解为给子类提供了可以进行循环枚举遍历的能力,而IEnumerator<T>
提供了一种枚举/遍历的方案。
!下面是从官方文档中整理出来的相关定义/声明!
首先是IEnumerable
的两个接口:
// // 摘要: // 公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。 若要浏览此类型的.NET Framework 源代码,请参阅Reference Source。 [ComVisible(true)] [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")] public interface IEnumerable { // // 摘要: // 返回循环访问集合的枚举数。 // // 返回结果: // 一个可用于循环访问集合的 System.Collections.IEnumerator 对象。 [DispId(-4)] IEnumerator GetEnumerator(); } } namespace System.Collections.Generic { // // 摘要: // 公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代。 若要浏览此类型的.NET Framework 源代码,请参阅 Reference Source。 // // 类型参数: // T: // 要枚举的对象的类型。 [TypeDependencyAttribute("System.SZArrayHelper")] public interface IEnumerable<out T> : IEnumerable { // // 摘要: // 返回一个循环访问集合的枚举器。 // // 返回结果: // 用于循环访问集合的枚举数。 IEnumerator<T> GetEnumerator(); } } ```
(虽然我现在还不知道具体协变和逆变用在这段代码里是为什么)
然后是IEnumerator<T>
的相关接口:
// // 摘要: // 提供一种用于释放非托管资源的机制。 若要浏览此类型的.NET Framework 源代码,请参阅Reference Source。 [ComVisible(true)] public interface IDisposable { // // 摘要: // 执行与释放或重置非托管资源关联的应用程序定义的任务。 void Dispose(); } } namespace System.Collections { // // 摘要: // 支持对非泛型集合的简单迭代。 [ComVisible(true)] [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")] public interface IEnumerator { // // 摘要: // 获取集合中位于枚举数当前位置的元素。 // // 返回结果: // 集合中位于枚举数当前位置的元素。 object Current { get; } // // 摘要: // 将枚举数推进到集合的下一个元素。 // // 返回结果: // 如果枚举数已成功地推进到下一个元素,则为 true;如果枚举数传递到集合的末尾,则为 false。 // // 异常: // T:System.InvalidOperationException: // 创建枚举器后,已修改该集合。 bool MoveNext(); // // 摘要: // 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。 // // 异常: // T:System.InvalidOperationException: // 创建枚举器后,已修改该集合。 void Reset(); } } namespace System.Collections.Generic { // // 摘要: // 支持在泛型集合上进行简单迭代。 // // 类型参数: // T: // 要枚举的对象的类型。 public interface IEnumerator<out T> : IDisposable, IEnumerator { // // 摘要: // 获取集合中位于枚举数当前位置的元素。 // // 返回结果: // 集合中位于枚举数当前位置的元素。 T Current { get; } } } ```
看到这里应该很清楚两者之间的关系了。