IEnumerable和IEnumerator

简介:

概述

IEnumerable和IEnumerator接口存在的意义:用来实现迭代的功能!

1
2
3
4
5
6
7
8
9
10
11
12
13
public  interface  IEnumerable
{
     IEnumerator GetEnumerator();
}
 
public  interface  IEnumerator
{
     object  Current {  get ; }
 
     bool  MoveNext();
 
     void  Reset();
}

迭代的原理

首先来说一下集合实现的原理:对于ArrayList、List<T>等集合,类中有一个私有的数组类型字段,向集合中添加数据时调用Add方法(将数据元素添加到私有数组字段中),而调用类的其他方法时,其实就是对私有数组类型字段的操作。

  ArrayList
  List

所以对于这些集合来说,本质上集合中的所有元素都是保存在一个私有数组类型的字段中,众所周知,对于ArrayList或者List<T>都可以使用foreach进行迭代,查看集合中的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
static  void  Main( string [] args)
{
     List< string > strs= new  List< string >();
     strs.Add( "DD" );
     strs.Add( "FF" );
     strs.Add( "VV" );
     strs.Add( "WW" );
     foreach  (String str  in  strs)
     {
         Console.WriteLine(str);
     }
     Console.ReadKey();
}

上述这个foreach的迭代的过程是如何实现的呢?foreach为什么可以逐个遍历所以集合中的元素呢?下面我们就用IL反汇编程序来查看上述代码的foreach部分的IL!

看不懂?没关系啦,那么我们就来大致的猜想一下,我们的foreach生成了这么一大坨的IL中居然有Enumerator什么的,难道跟这个有关系吗?恰巧听说IEnumerable和IEnumrator用来实现迭代,恰恰巧我们的ArrayList、List<T>集合都是实现了IEnumerable接口。那么我们就来做的大胆的假设,foreach其实就是执行跟IEnumerable和IEnumrator接口相关的代码,并对保存集合的私有数组字段的索引进行操作,从而来实现迭代的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static  void  Main( string [] args)
{
     List< string > strs= new  List< string >();
     strs.Add( "DD" );
     strs.Add( "FF" );
     strs.Add( "VV" );
     strs.Add( "WW" );
     IEnumerator< string > items = strs.GetEnumerator();
     while  (items.MoveNext())
     {
         Console.WriteLine(items.Current);
     }
     Console.ReadKey();
}

这段代码也同样实现了对集合元素迭代的功能!在来看一下这个迭代生成的相关IL。

嘿嘿,对比两者生成的IL,目测他们的执行过程中调用的IL指令大体上是一致的(IL指令啥的暂时我也不是很了解),所以我们的猜想应该是正确的,foreach在本质上其实就是通过ArrayList、List<T>中定义的GetEnumerator方法,以及后续的代码实现的!下面就来看看List<T>中是如何定义的。

  List<T>

哇哦,原来迭代器是这样的呀!!!!

自定义一个简单的支持迭代的集合

下面我们就来自定义一个支持迭代器的集合

复制代码
public class UserDefinedCollection<T>:IEnumerable<T>
    {
        private List<T> list = new List<T>();

        public UserDefinedCollection(List<T> param)
        {
            list = param;
        }
        public IEnumerator<T> GetEnumerator()
        {
            return new UserDefinedEnum<T>(list);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        private sealed class UserDefinedEnum<T>:IEnumerator<T>
        {
            private List<T> list = null;
            private int _CurrentIndex;
            private T _CurrentElement;

            public UserDefinedEnum(List<T> param)
            {
                this.list = param;
                this._CurrentIndex = 0;
                _CurrentElement = default(T);
                
            }

            public T Current
            {
                get 
                {
                    return _CurrentElement;
                }
            }

            object IEnumerator.Current
            {
                get { return Current; }
            }

            public bool MoveNext()
            {
                if (this._CurrentIndex < this.list.Count)
                {
                    this._CurrentElement = this.list[this._CurrentIndex++];
                    return true;
                }
                return false;
            }

            public void Reset()
            {
                this._CurrentElement = default(T);
                this._CurrentIndex = 0;
            }
            public void Dispose()
            {
                
            }
        }

    }
复制代码

 测试自定义集合的迭代功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List< string > strs= new  List< string >();
strs.Add( "DD" );
strs.Add( "FF" );
strs.Add( "VV" );
strs.Add( "WW" );
UserDefinedCollection<String> user =  new  UserDefinedCollection< string >(strs);
IEnumerator< string > iEnumerator = user.GetEnumerator();
 
while  (iEnumerator.MoveNext())
{
     Console.WriteLine(iEnumerator.Current);
}
 
foreach  (String str  in  user)
{
     Console.WriteLine(str);
}

 

扩展:由模型绑定中,绑定泛型类型时学习到泛型相关的知识!

  


本文转自武沛齐博客园博客,原文链接:http://www.cnblogs.com/wupeiqi/p/3472980.html,如需转载请自行联系原作者

目录
相关文章
|
7月前
|
存储 C# 索引
C# | 比较IEnumerable、List、数组
IEnumerable`定义了一组用于枚举集合的方法,包括`GetEnumerator`方法,该方法返回一个实现了`IEnumerator`接口的对象,用于枚举集合中的每个元素。`List`和数组都可以使用`foreach`循环来遍历其中的元素,这是因为它们都实现了`IEnumerable`接口。 由于数组在内存中开辟了一段连续的空间,因此可以直接通过索引访问元素,访问速度很快。而 List 则需要通过指针或引用来访问元素,速度相对较慢。 由于数组的大小是固定的,当需要添加或删除元素时,需要重新创建一个新数组,将原数组中的元素复制到新数组中,并添加或删除元素。
244 0
C# | 比较IEnumerable、List、数组
|
C# 索引
C#List转IList方法
List类:表示可通过索引访问的对象的强类型列表,提供用于对列表进行搜索、排序和操作的方法。 IList接口:表示可按照索引单独访问的一组对象。
296 0
C#List转IList方法
|
SQL .NET 数据库
IEnumerable和IQueryable在使用时的区别
最近在调研数据库查询时因使用IEnumerable进行Linq to entity的操作,造成数据库访问缓慢。此文讲述的便是IEnumerable和IQueryable的区别。 微软对IEnumerable的定义使用场景为Linq to Object,也就是涉及到内存操作时使用。
1315 0