C# IEnumerable接口和IEnumerator 接口

介绍

IEnumerable 是可以枚举的所有非泛型集合的基本接口

IEnumerator 支持对非泛型集合进行简单的迭代,即:迭代器

IEnumerable 和 IEnumerator 接口搭配使用,实现 自定义集合

IEnumerable

命名空间: System.Collections

作用

支持 foreach 语句

类比java

相当于 JAVA Iterable 迭代器

方法

  • GetEnumerator():返回一个可用于循环访问集合的IEnumerator对象

IEnumerator

命名空间: System.Collections

类比java

相当于 JAVA Iterator 接口

属性

  • Current:获取集合中枚举器当前位置的元素。

方法

  • MoveNext():将枚举器推进到集合的下一个元素。

  • Reset():将枚举器设置为其初始位置,该位置位于集合中的第一个元素之前。

案例

封装类

using System;
using System.Collections;

// Simple business object.
public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

实现自定义集合

实现 IEnumerable 接口

// Collection of Person objects. This class
// implements IEnumerable so that it can be used
// with ForEach syntax.
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];
        }
    }

// Implementation for the GetEnumerator method.
    IEnumerator IEnumerable.GetEnumerator()
    {
       return (IEnumerator) GetEnumerator();
    }

    public PeopleEnum GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

实现该集合的迭代器

实现 IEnumerator 接口

// When you implement IEnumerable, you must also implement IEnumerator.
public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    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
    {
        get
        {
            return Current;
        }
    }

    public Person Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}

测试类

class App
{
    static void Main()
    {
        Person[] peopleArray = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
            new Person("Sue", "Rabon"),
        };

        People peopleList = new People(peopleArray);
        foreach (Person p in peopleList)
            Console.WriteLine(p.firstName + " " + p.lastName);
    }
}

相当于下面代码

class App
{
    static void Main()
    {
        Person[] peopleArray = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
            new Person("Sue", "Rabon"),
        };

        People peopleList = new People(peopleArray);
        IEnumerator myie = People.GetEnumerator();
        //重置当前项,相当于把指针移到初始位置:position = -1; 一开始认识数组的索引从“0”开始
        myie.Reset();
        //向前移动一个索引,返回Bool类型,判断是否超出下标
        while (myie.MoveNext())
        {
             int i = (int)myie.Current;//从Object转成对应类型
             Console.WriteLine("Value: {0}", i);
        }
    }
}

判断 IEnumerable中没有元素

方式一

if (mylist != null && mylist.Any())
{
    // The list is not null or empty
}

方式二

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
    // The list is not null or empty
}

参考:
https://www.cnblogs.com/wml-it/p/14776958.html