理解foreach运行原理:IEnumerable<T> & IEnumerator<T>以及相关系统api

首先是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; }
    } } ```

看到这里应该很清楚两者之间的关系了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值