C#c ienumerable转list和IEnumerator的区别,如何实现

List &T&是ArrayList的泛型,ArrayList里边的数据类型是object,List &T&里边的是具体的某种类型,ArrayList类似于向量,可以存储不同的数据类型在一个数组里边(转换为了object)。 一般使用的时候尽量使用List &T&,因为ArrayList存取都要进行一次转换。 []类型的数组类似于List &T&,不同的是[]是定长的,而List &T&是长度可变的数组ICollection主要针对静态集合;IList主要针对动态集合 IEnumerable &T&继承自IEnumerable ICollection &T&继承自IEnumerable &T& IList &T&继承自ICollection &T& IEnumerable接口 实现了IEnumerable接口的集合表明该集合能够提供一个enumerator(枚举器)对象,支持当前的遍历集合。IEnumerable接口只有一个成员GetEnumerator()方法。 IList接口和ArrayList类的目的是实现动态数组,ArrayList是IList的一个实现。IEnumerable表明对象是不确定类型的集合并支持简单迭代,是不是定长根本不关心... IEnumerable &T&表明对象是指定类型的集合并支持简单迭代,是不是定长根本不关心... ICollection是IEnumerable接口的派生接口,表明对象是不确定类型的集合并支持简单迭代,而且定义了集合的大小、枚举数和同步方法,这里的大小是指可以是定长的也可以是不定长的... IList是ICollection和IEnumerable的派生接口,表明对象是不确定类型的集合并支持简单迭代,而且定义了集合的大小、枚举数和同步方法,还可以按照索引单独访问,这里的大小是指可以是定长的也可以是不定长的... ArrayList类是IList接口的实现,表明对象是不确定类型的大小可按需动态增加的数组... List &T&类是IList &T&接口的实现,是ArrayList类的泛型等效类并增强了功能,表明对象是可通过索引访问的对象的强类型列表...在.NET 2.0以上可以完全代替ArrayList,就是说ArrayList已经被淘汰... 而动态数组和链表在本质上是不同的...在.NET 2.0以上有双向链表LinkedList &T&泛型类,它也是继承自ICollection &T&,IEnumerable &T&,ICollection,IEnumerable...能够使用foreach遍历的集合,必须继承IEnumberable(或IEnumerable &T&泛型接口)接口。 IEnumberable接口只有一个方法: IEnumerator GetEnumberator(){}//返回一个IEnumberator类型的对象,该对象实现System.Collection.IEnumerator接口。 interface IEnumberator { object Current{} bool MoveNext(); void Reset(); }在程序中拼凑sql时,可以这样使用List &T& List &SqlParameter& list=new List &SqlParameter&(); list.Add(new SqlParameter("参数名","参数值")); ... SqlParameter[] para=list.ToArray(); ...
阅读(...) 评论()2105人阅读
在C#中,一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方式返回IEnumerator object)。
枚举数只允许读取集合中的数据。枚举数无法用于修改基础集合。
函数原型如下:
&&& public interface IEnumerable
&&&&&&& //IEnumerable只有一个方法,返回可循环访问集合的枚举数。
&&&&&&& IEnumerator GetEnumerator();
&&& public interface IEnumerator
&&&&&&& // 方法
&&&&&&& //移到集合的下一个元素。如果成功则返回为 true;如果超过集合结尾,则返回false。
&&&&&&& bool MoveNext();
&&&&&&& // 将集合设置为初始位置,该位置位于集合中第一个元素之前
&&&&&&& void Reset();
&&&&&&& // 属性:获取集合中的当前元素
&&&&&&& object Current { }
&&& //一个结构体,用于类myEnum
&&& struct point
&&& //我们的一个派生于IEnumerable和IEnumerator接口的自定义类
&&& class myEnum :IEnumerable,IEnumerator
&&&&&&& //定义索引
&&&&&&& //定义一个point结构的数组
&&&&&&& private point[]
&&&&&&& //类的构造函数,用于初始化point结构数组
&&&&&&& public myEnum(int numofpoint)
&&&&&&&&&&& this.index = -1;
&&&&&&&&&&& points = new point[numofpoint];
&&&&&&&&&&& for (int i = 0; i & points.L i++)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& points[i].x =
&&&&&&&&&&&&&&& points[i].y = i*i;
&&&&&&&&&&&&&&& points[i].z = i*i*i;
&&&&&&&&&&& }
&&&&&&& //实现IEnumerable接口的GetEnumerator方法,返回一个IEnumerator,这里返回我们的自定义类,因为要对这个类的对象进行迭代
&&&&&&& public IEnumerator GetEnumerator()
&&&&&&&&&&& //这里太让我激动了,原来就是返回this这么简单,因为this本身已经是一个ienumerator了,
&&&&&&&&&&& //不过唯一的问题在于当重复迭代这个对象时,index整型字段还原成-1的问题,
&&&&&&&&&&& //所以要在movenext()方法return false之前还原index的值。
&&&&&&&&&&& return (IEnumerator)& //return points.GetEnumerator(); 均可
&&&&&&& //实现IEnumerator接口的Reset方法,将集合索引置于第一个元素之前
&&&&&&& //枚举数被定位于集合中第一个元素的前面。Reset 也将枚举数返回到此位置。在此位置,调用 Current 会引发异常。因此,在读取 Current 的值之前,必须调用 MoveNext 将枚举数提前到集合的第一个元素。
&&&&&&& public void Reset()
&&&&&&&&&&& index = -1;
&&&&&&& //实现IEnumerator接口的Current属性,返回一个自定义的point结构,即point数组的第index元素
&&&&&&& //在调用 MoveNext 或 Reset 之前,Current 返回同一对象。MoveNext 将 Current 设置为下一个元素。
&&&&&&& public object Current
&&&&&&&&&&& get
&&&&&&&&&&& {
&&&&&&&&&&&&&&& try
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& return points[index];
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& catch (IndexOutOfRangeException)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& throw new InvalidOperationException();
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&& //实现IEnumerator接口的MoveNext方法,用于向前访问集合元素,如果超出集合范围,返回false
&&&&&&& //在传递到集合的末尾之后,枚举数放在集合中最后一个元素后面,且调用 MoveNext 会返回 false。如果最后一次调用 MoveNext 返回 false,则调用 Current 会引发异常。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext。
&&&&&&& public bool MoveNext()
&&&&&&&&&&& index++;
&&&&&&&&&&& if (index &= points.Length)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& //再返回false之前还原index的值(-1)
&&&&&&&&&&&&&&& Reset();
&&&&&&&&&&&&&&&
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&&&&&&
&&& 只要集合保持不变,枚举数就将保持有效。如果对集合进行了更改(例如添加、修改或删除元素),则该枚举数将失效且不可恢复,并且下一次对 MoveNext 或 Reset 的调用将引发 InvalidOperationException。如果在 MoveNext 和 Current 之间修改集合,那么即使枚举数已经无效,Current 也将返回它所设置成的元素。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:190058次
积分:3195
积分:3195
排名:第7940名
原创:129篇
转载:14篇
评论:14条
(7)(13)(19)(31)(14)(3)(1)(4)(17)(1)(4)(3)(11)(15)3387人阅读
&&& 在C#中,如果一个类要使用foreach结构来实现迭代,就必须实现IEnumerable或IEnumerator接口。其中,IEnumerator接口定义了实现枚举器模式的方法IEnumerator.MoveNext()和IEnumerator.Reset()和成员属性IEnumerator.Count,而IEnumerable接口的唯一方法IEnumerable.GetEnumerator()仅用来返回一个IEnumerator对象,用来间接实现一个IEnumerator接口。
&&& 而泛型的IEnumerator&T&和IEnumerable&T&接口与普通类型的相似,它们是普通类型枚举器接口的泛化形式。但实现IEnumerable&T&接口,需要实现两个GetEnumerator,分别为IEnumerator IEnumerable.GetEnumerator()和IEnumerator&T&
GetEnumerator()。
&&& 1、IEnumerator的实现
&&&&&&& 自己找例子看.....
&&&&2、IEnumerable的实现
&&&&&(1)返回一个IEnumerator
&&&&&&&&&&& 自己找例子看.....
&&&&&(2)使用yield return(yield break)语法
&&&&&&&&&& 自己找例子看看.....
&&& 3、一种混合实现的结构
&&&&&& 在一个类(如ClassName1)中实现IEnumerable接口,而在另一个类(如ClassName1Enumerator)中实现IEnumerator接口,并在ClassName1中的GetEnumerator()方法中,返回一个用ClassName1实例化的ClassName1Enumerator对象。
&&&& 4、枚举器具体介绍&
&&&&&& 枚举器可用于读取集合中的数据,但不能用于修改基础集合。
最初,枚举器被定位于集合中第一个元素的前面。
方法还将枚举器返回到此位置。在此位置,调用 属性会引发异常。因此,在读取
的值之前,必须先通过调用 方法将枚举器前移到集合中的第一个元素。
&&&&&& 在调用
返回同一对象。 将
设置到下一个元素。
如果 越过集合的末尾,则枚举器将放置在集合中最后一个元素的后面,而且
返回false。当枚举器位于此位置时,对
的后续调用也返回false。如果最后一次调用
返回了false,则调用
会引发异常。若要再次将
设置为集合的第一个元素,可以调用,然后再调用。
只要该集合保持不变,枚举器也就保持有效。如果对该集合进行了更改(例如添加、修改或删除元素),则该枚举数变为无效(这一变化是不可恢复的),并且下次调用
或 将引发。如果在
和 之间修改了集合,则
会返回已将它设置为的元素,即使该枚举数已失效。
&&&&&& 该枚举器不具有独占访问集合的权限;因此,枚举整个集合本质上不是一个线程安全的过程。即使集合已同步,其他线程仍可以修改集合,从而使枚举数引发异常。若要确保枚举过程中的线程安全性,可以在整个枚举期间锁定集合,或者捕获由其他线程进行的更改所导致的异常。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:139670次
积分:1603
积分:1603
排名:第19020名
原创:10篇
转载:82篇
(1)(4)(1)(36)(9)(24)(12)(4)(1)

我要回帖

更多关于 c ienumerator yield 的文章

 

随机推荐