当前位置: 移动技术网 > IT编程>开发语言>c# > IEnumerable和IEnumerator详解

IEnumerable和IEnumerator详解

2019年12月04日  | 移动技术网IT编程  | 我要评论

引言

ienumerable是可枚举的所有非泛型集合的基接口, ienumerable包含一个方法getenumerator(),该方法返回一个ienumerator;ienumerator提供通过current属性以及movenext()和reset()方法来循环访问集合的功能。

ienumerable 接口

公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。接口源码如下:

public interface ienumerable
{
    [dispid(-4), __dynamicallyinvokable]
    ienumerator getenumerator();
}

ienumerator 接口

支持对非泛型集合的简单迭代。接口源码如下:

public interface ienumerator
{
    [__dynamicallyinvokable]
    bool movenext();
    [__dynamicallyinvokable]
    object current { [__dynamicallyinvokable] get; }
    [__dynamicallyinvokable]
    void reset();
}

举例说明

示例演示了通过实现ienumerable和ienumerator接口来循环访问自定义集合的最佳实践。

定义一个简单的实体类:

public class person
    {
        public person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
        public string name;
        public int age;
    }

定义一个实体类的集合,继承ienumerate:

 public class people : ienumerable
    {
        private person[] _people;
        public people(person[] parray)
        {
            _people = new person[parray.length];
            for (int i = 0; i < parray.length; i++)
            {
                _people[i] = parray[i];
            }
        }
        /// <summary>
        /// getenumerator方法的实现
        /// </summary>
        /// <returns></returns>
        ienumerator ienumerable.getenumerator()
        {
            return getenumerator();
        }
        public peopleenum getenumerator()
        {
            return new peopleenum(_people);
        }
    }

定义一个枚举器,继承ienumerator:

public class peopleenum : ienumerator
    {
        public person[] _people;

        /// <summary>
        /// 枚举器位于第一个元素之前直到第一个movenext()调用。
        /// </summary>
        private int position = -1;
        public peopleenum(person[] list)
        {
            _people = list;
        }

        public bool movenext()
        {
            position++;
            return position < _people.length;
        }

        public void reset()
        {
            position = -1;
        }

        object ienumerator.current => current;

        public person current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (indexoutofrangeexception)
                {
                    throw new invalidoperationexception();
                }
            }
        }
    }

具体调用:

 person[] peoplearray = new person[3]
            {
                new person("张三", 15),
                new person("李四", 18),
                new person("王五", 21),
            };
 people peoplelist = new people(peoplearray);
            
 foreach (person p in peoplelist)
          console.writeline(p.name + "\t" + p.age);

输出:

其中,上边调用中foreach等价于

ienumerator enumeratorsimple = peoplelist.getenumerator();
while (enumeratorsimple.movenext())
   {
        person p = enumeratorsimple.current as person;
        console.writeline(p?.name + "\t" + p?.age);
   }

通过例子,可以得出:

  • 实现一个自定义集合,继承于ienumerate,必须实现一个枚举器;
  • c# 语言的foreach语句隐藏了枚举数的复杂性,因此, 建议foreach使用, 而不是直接操作枚举器;
  • 枚举器可用于读取集合中的数据,但不能用于修改基础集合。

总结

ienumerable代表继承此接口的类(比如arraylist,ilist,list<t>等)可以获取一个ienumerator来实现枚举这个类中包含的集合中的元素的功能,是 .net framework 中最基本的集合访问器。在编程中,lambda表达式通过select()或者where()返回的变量为ienumerate<t>,此时我们可以通过foreach遍历。希望本文对你有所帮助,下一篇介绍lambda中的select和where,感兴趣的朋友可以加关注,欢迎留言交流!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网