c#中关于IEnumerator与IEnumerable接口 您所在的位置:网站首页 继承泛型接口的实现类 c#中关于IEnumerator与IEnumerable接口

c#中关于IEnumerator与IEnumerable接口

2024-06-27 04:23| 来源: 网络整理| 查看: 265

c#中关于IEnumerator与IEnumerable接口 前言一、IEnumerator与IEnumerable接口是什么?二、运用举例1.实现代码2.结果输出3.自实现Foreach过程 总结

前言

在平时敲代码的过程中发现了Foreach遍历,发现实现IEnumerable接口(实现方法后,删除继承接口IEnumerable也能使用)就能使用,遂作进一步深入。

一、IEnumerator与IEnumerable接口是什么?

首先来看看IEnumerator与IEnumerable及IEnumerator与IEnumerable的系统代码:

1.IEnumerable(可迭代的)

namespace System.Collections { // // 摘要: // 公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。 public interface IEnumerable { // // 摘要: // 返回一个循环访问集合的枚举器。 // // 返回结果: // 可用于循环访问集合的 System.Collections.IEnumerator 对象。 IEnumerator GetEnumerator(); } } 派生类需要实现方法: public IEnumerator GetEnumerator(){}//返回的是IEnumerable(迭代器)

2.IEnumerable(泛型)

namespace System.Collections.Generic { // // 摘要: // 公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代。 // // 类型参数: // T: // 要枚举的对象的类型。此类型参数是协变。即可以使用指定的类型或派生程度更高的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。 public interface IEnumerable : IEnumerable { // // 摘要: // 返回一个循环访问集合的枚举器。 // // 返回结果: // 可用于循环访问集合的 System.Collections.Generic.IEnumerator`1。 IEnumerator GetEnumerator(); } } 由于继承了IEnumerable接口,所以派生类需要实现: public IEnumerator GetEnumerator(){}//返回的是IEnumerable(泛型迭代器) 及 IEnumerator IEnumerable.GetEnumerator(){}//IEnumerable接口继承过来的,私有化了

3.IEnumerator(迭代器)

namespace System.Collections { // // 摘要: // 支持对非泛型集合的简单迭代。 public interface IEnumerator { // // 摘要: // 获取集合中的当前元素。 // // 返回结果: // 集合中的当前元素。 object Current { get; } // // 摘要: // 将枚举数推进到集合的下一个元素。 // // 返回结果: // 如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。 // // 异常: // T:System.InvalidOperationException: // 在创建了枚举数后集合被修改了。 bool MoveNext(); // // 摘要: // 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。 // // 异常: // T:System.InvalidOperationException: // 在创建了枚举数后集合被修改了。 void Reset(); } } 派生类需要实现属性与方法: public object Current{get{}} public bool MoveNext(){ } public void Reset(){}

4.IEnumerator(泛型)

namespace System.Collections.Generic { // // 摘要: // 支持在泛型集合上进行简单迭代。 // // 类型参数: // T: // 要枚举的对象的类型。此类型参数是协变。即可以使用指定的类型或派生程度更高的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。 public interface IEnumerator : IDisposable, IEnumerator { // // 摘要: // 获取集合中位于枚举数当前位置的元素。 // // 返回结果: // 集合中位于枚举数当前位置的元素。 T Current { get; } } } namespace System { // // 摘要: // 定义一种释放分配的资源的方法。 [ComVisible(true)] public interface IDisposable { // // 摘要: // 执行与释放或重置非托管资源相关的应用程序定义的任务。 void Dispose(); } } 派生类需要实现属性与方法: publi T Current{get{}} object Current{get{}} //继承于IEnumerator,私有化了 public bool MoveNext(){ } public void Reset(){} public void Dispose(){} //继承与IDisposable 二、运用举例

在此,仅通过简单的实例来实现自定义类型使之可以进行Foreach遍历。

1.实现代码

类代码如下:

class Person //首先定义一个元素类(人) { public int mAge; //里面只有一个年龄 public Person(int age) //实例化时需要赋值 { mAge = age; } } class Persons : IEnumerable//可迭代的 这边再定义一个人们类,用于存放人这一元素,类似List(追求简单,没实现Add方法) { Person[] mPersons; //字段存放数据 public Persons(Person[] persons) //由于没有Add方法,实例化时直接传入 { mPersons = persons; } public IEnumerator GetEnumerator() //实现IEnumerator接口的方法,返回迭代器 { return new Enumerator(mPersons); //为了方便,自己写了迭代器(IEnumerator)的派生类 } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(mPersons); } //根据需求Class与Struct都可以 class Enumerator : IEnumerator //迭代器 //IEnumerator只需要实现Current,MoveNext和Reset { //IEnumerator需要实现Current,MoveNext和Reset及Dispose Person mCurrent; //存放当前迭代数据 Person[] mArray; //用于迭代的数据组 int mIndex; //迭代的索引 public Enumerator(Person[] arr) //实例化时,初始化字段数据 { mArray = arr; mIndex = 0; mCurrent = mArray[mIndex]; } public Person Current //属性获取当前数据 { get { return mCurrent; } } object IEnumerator.Current { get { return mCurrent; } } public void Dispose() //继承自IDisposable,资源释放时运行 { Console.WriteLine("我悄悄的释放了"); } public bool MoveNext() //foreach会循环调用此函数 { //当数据没有下一个的时候,需要返回false Console.WriteLine("到MoveNext一游"); if (mIndex > mArray.Length - 1) //实现了更新数据给本地数据(mCurrent) { Reset(); return false; } else { mCurrent = mArray[mIndex]; mIndex = mIndex + 1; return true; } } public void Reset() //数据初始化方法 { mIndex = 0; Console.WriteLine("初始化一下"); } } }

主流程代码如下:

Person[] PersonArr = { new Person(55), //定义人数组元素 new Person(35), new Person(92), new Person(10), new Person(200), new Person(91) }; Persons People = new Persons(PersonArr); //实例化人们类 int i = 1; #region 我是个标签 Console.WriteLine("我还没进Foreach"); foreach (var item in People) //第一次进入就会去调用MoveNext()方法 { Console.WriteLine($"第{i}进入,有点激动"); i++; Console.WriteLine($"{item.mAge}岁人一枚"); } Console.WriteLine("我出来啦"); Console.ReadKey(); #endregion 2.结果输出

在这里插入图片描述

3.自实现Foreach过程

通过对上面运行结果分析,我们可以尝试自实现此过程,将上述#region段中的代码替换如下:

IEnumerator mitem = People.GetEnumerator(); //获取迭代器(IEnumerator)实例 Console.WriteLine("我还没进Foreach"); while (mitem.MoveNext()) //通过MoveNext判断数据是否穷尽 { Console.WriteLine($"第{i}进入,有点激动"); i++; Console.WriteLine($"{mitem.Current.mAge}岁人一枚"); //获取迭代器当前数据(Current) } mitem.Dispose(); //用完释放 Console.WriteLine("我出来啦"); Console.ReadKey();

运行结果是一样的,再次就不做展示了。

总结

本文只通过IEnumerable与IEnumerator实现了自定义类的Foreach遍历,看起来实现步骤还是很多复杂有没有办法简化呢(yield return)?自实现foreach过程与系统foreach结果相同运行结果也相同么?未知还很多,我们下次再见拜拜。

父在观其志,父没观其行。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有