zoukankan      html  css  js  c++  java
  • IEnumerable和IEnumerator详解

    引言

    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,感兴趣的朋友可以加关注,欢迎留言交流!

    公众号
    作者:码探长
    公众号:码探长
    如果你想得到探长更多相关技术文章的消息推送,或者获取相关下载资源,可以扫描左边二维码(或者长按识别二维码)关注个人公众号)。
    本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    多线程频繁上锁同步还不如用单线程
    1分钟左右随机生成2000万行随机字符串
    语言:抽象,封装,底层,低级
    构建WDK驱动出现fatal error U1087: cannot have : and :: dependents for same target
    Cmake编译成静态库
    VMware虚拟机相关文件问题
    输出流重定向
    How can I let the compiled script depend on something dynamic
    应用服务攻击工具clusterd
    Kali Linux缺少ifconfig命令
  • 原文地址:https://www.cnblogs.com/matanzhang/p/11978715.html
Copyright © 2011-2022 走看看