• 实现IEnumerable 和 IEnumerator, 使类型具备枚举功能的注意


    实现IEnumerable接口的类,可以支持foreach循环遍历对象的集合元素

    IEnumerable:
    IEnumerator GetEnumerator() 返回可循环访问集合的枚举数。

    IEnumerator:
    object Current 获取集合中的当前元素。
    bool MoveNext() 将枚举数推进到集合的下一个元素。
    如果枚举数 成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false
    void Reset() 将枚举数设置为其初始位置,该位置位于集合中第一个元 素之前。


    背景知识

    在现实应用中,对于集合以及枚举这些集合的需求非常普遍, 因此在.NET中集合所依赖的接口被设计为公共的。想要实现对象的枚举就必须继承IEnumerable接口。
    public interface IEnumerable
    {
          public IEnumerator GetEnumerator();
    }

    它 只有一个成员:GetEnumerator方法。该方法返回一个实际的枚举器(enumerator)对象。那么要定义一个枚举器就要必 须实现IEnumrator接口:
    public interface IEnumerator
    {
          public Boolean MoveNext();
          public Object Current { get; }
          public void Reset();
    }

    这里我不想把MSDN上的解释在重复一遍,我只是提出一个问题,也就是说如果我们希望一个类型支持 枚举特性,那么我们就必须还要额外定义一个辅助类型来实现IEnumerator的所有方法。这个辅助类型通常被定义为一个Nested class声明在主类内部。这样在实现的时候我们发现,在app调用GetEnumerator()方法时,我们需要构造一个辅助类型的实例作为返回值。 这时我们有两种做法:

    1. 把主类型的数据当时的静态快照,以复本的形式在辅助类型初始化时赋值给辅助类型实例 (enumerator)
    2. 把主类型的数据的引用传递给辅助类型,保证app访问的实时更新的数据

    这 的确提供了一定的灵活性给用户, 在app想要枚举某个实例的数据集合时,也可以有两种方法:

    1. 使用各接口暴露的方法
    2. 使用foreach语句:foreach( type-identifier in expression ) { embedded-statement }

    对于foreach,我想提两句,要想使用它所必须满足的条件:

    1. expression必须实现GetEnumerator()方法
    2. GetEnumerator() 放回的实例必须实现MoveNext()和Current两个公共方法。

    问题1:为什么需要两个接口,而不把Current, MoveNext和Reset成员都放到IEnumerable接口中?

    答 案:采用这种间接的方式是为了提高灵活性。你可以利用IEnumerator来决定如何展示你想要暴露的内部数据给客户。当然你可以在一个类型中同时实现 这两个接口:class MyArrayData : IEnumerable, IEnumerator { ... };这样可以节省了一些创建辅助类型从而带来的CPU和Memory开销。一般建议在如下情况时,使用这种结合的方法:

    1. 当 数据没有存储在系统已有的集合中,否则可以直接把集合的enumerator返回
    2. 当你的自定义的Enumerator需要做 出了移动游标和返回数据之外的其他操作

    问题2:如果集合 中的数据是值类型,那么有什么性能上的考虑么?

    答案:由于值类型在传入ArrayList这样的集合容器中时,需要 box,在传出的时候需要unbox。经过很多验证,这种操作时非常耗时的。因此,我们可以在实现标准的枚举方法的时候,可以在暴露一些自定义的 GetEnumerator, MoveNext和Current方法(其实, 标准的接口只是调用自定义的接口而已的一个wrapper方法)。这样既可以在自己的方法中避免了不必要的装箱和拆箱操作(用自定义方法,而不能使用 foreach语句),又可以被约定俗成的foreach句法所调用(当然,这种情况下就不能避免box和unbox了)。

  • 相关阅读:
    @responseBody注解的使用
    springmvc下的省市县三级联动
    select 动态添加option函数
    清空select标签中option选项的4种不同方式
    javascript删除option选项的多种方法总结
    js如何获取select下拉框的value以及文本内容
    如何设置select下拉禁止选择
    java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符
    转:通过他人完成任务的艺术
    ***周鸿祎谈创业:很多程序员高智商 但我一看就知道他们不会成功
  • 原文地址:https://www.cnblogs.com/goody9807/p/1733781.html
Copyright © 2020-2023  润新知