自定义集合类实现接口IEnumrable和IEnumrator,遍历/迭代自定义集合对象

先来说说IEnumrable和IEnumrator接口,IEnumrable接口成员如下:
    public interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }
IEnumrable是可枚举类型,什么是可枚举类型呢?简单说,就是实现了IEnumrable接口的类型,所有能用foreach循环的类型都是可枚举类型。

可迭代类型,迭代即遍历,可迭代,即可遍历,所以只要一个类型实现了IEnumrable接口,就可以进行对它进行迭代(遍历)。
这个接口只有一个成员GetEnumerator()方法,返回一个IEnumrator接口对象,我们再看看IEnumrator的接口定义:
    public interface IEnumerator
    {
        object Current { get; }
        bool MoveNext();
        void Reset();
    }

IEnumrator枚举器,只有三个成员:只读属性Current,方法Move(),方法Reset()。
Reset()方法将集合游标复位至-1位置,为下一次向前遍历整个集合做准备;
Current只读属性,获取当前游标所在位置的集合元素;
MoveNext()方法,将游标移至下一个集合元素位置,为获取新元素做准备;
通过上面三个成员介绍,不难看出,如果我们创建一个集合类,实现IEnumrable接口的GetEnumrator()方法,再实现IEnumrator接口的三个成员:属性Current,方法Move(),方法Reset().就能实现对自定义集合对象的遍历.

一般来说有两种方式实现集合类的IEnumrable和IEnumrator接口成员,从而实现对集合类的元素遍历。
第一种,按照.Net集合类的接口实现方式,集合类继承IEnumrable接口并实现GetEnumrator()方法,方法内返回IEnumrator对象,然后创建一个类Enumrator_People,继承IEnumrator接口,实现该接口的三个成员.如下demo:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;namespace 自定义集合类
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){//People是自定义的集合类型,创建一个集合对象peo,然后将集合元素逐一添加进来,再进行peo集合遍历集合中的元素!//通过合类的无参构造函数,创建一个空集合对象peoPeople peo = new People();//通过Add方法添加集合元素peo.Add(new Person("LuSU"));peo.Add(new Person("ZhouYU"));//AddRange方法添加集合元素peo.AddRange(new Person[] { new Person("LiuBei"), new Person("SunQuan") });peo.AddRange(new List<Person> { new Person("CaoCao"), new Person("ZhuGeliang") });peo.RemoveAt(0);foreach (Person person in peo){Console.WriteLine(person.name);}Console.ReadKey();Console.WriteLine("\r\n");//利用构造函数初始化一个集合类对象List<Person> peopleList = new List<Person> { new Person("LI"), new Person("SA") };People people = new People(peopleList);foreach (Person person in people){Console.Write($"{person.name},");}Console.ReadKey();}}//自定义集合类的元素类型public class Person{public string name { get; set; }public Person(string name){this.name = name;}}//自定义集合类public class People : IEnumerable{static int _position = -1;private List<Person> _people = new List<Person>();public People(){}public People(List<Person> people){_people = people;}public void Add(Person per){_people.Add(per);}public void AddRange(IEnumerable<Person> personcollection){_people.AddRange(personcollection);}public void Remove(Person per){_people.Remove(per);}public void RemoveAt(int index){if(index < _people.Count)_people.RemoveAt(index);}public void RemoveRange(int Fromindex,int cnt){if (Fromindex + cnt <= _people.Count)_people.RemoveRange(Fromindex, cnt);}public void RemoveAll(){_people.Clear();}public object Current{get{return _people[_position];}}public bool MoveNext(){_position++;if (_position < _people.Count){return true;}else{return false;}}public void Reset(){_position = -1;}public IEnumerator GetEnumerator(){return new Enumrator_People(_people);}}public class Enumrator_People : IEnumerator{List<Person> _p;public Enumrator_People(List<Person> p){_p = p;}int _position = -1;public object Current{get{return _p[_position];}}public bool MoveNext(){_position++;if (_position < _p.Count){return true;}else{return false;}}public void Reset(){_position = -1;}}
}

运行demo,执行结果如下:

第二种,集合类继承IEnumrable和IEnumrator接口,并在集合类内实现这两个接口的所有成员,也能实现对自定义集合类对象的迭代,如下demo:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 自定义集合类
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){List<Person> peopleList = new List<Person> { new Person("LI"), new Person("SA") };People people = new People(peopleList);foreach (Person person in people){Console.Write($"{person.name},");}Console.ReadKey();}}//自定义集合类的元素类型public class Person{public string name { get; set; }public Person(string name){this.name = name;}}//自定义集合类public class People : IEnumerator,IEnumerable{static int _position = -1;private List<Person> _p;public People(){}public People(List<Person> peo){_p = peo;}public object Current{get{return _p[_position];}}public IEnumerator GetEnumerator(){//this代表当前集合类,而当前集合类实现了IEnumrator接口,自然就可以把this作为IEnumrator对象返回给GetEnumrator方法.return this;}public bool MoveNext(){_position++;if (_position < _p.Count){return true;}else{return false;}}public void Reset(){_position = -1;}}
}

还有另一中实现IEnumrable接口内的GetIEnumrator()方法,从而返回Enumrator接口对象,在GetIEnumrator()方法内用关键字yield return返回集合元素。
yield关键字做了什么工作呢,通过代码示例可以看出,yield关键字是将return后面的内容,转换成了IEnumrator对象,返回给IEnumrator.
其实yield内部就是实现了IEnumrator接口的三个成员,我是这么理解的,这样就不用再额外写IEnumrator接口的三个成员的具体实现代码了,如下demo调试通过,奈斯!!!

using System;
using System.Collections;
using System.Collections.Generic;namespace 自定义集合类yield关键字
{class Program{static void Main(string[] args){List<Person> peopleList = new List<Person> { new Person("LI"), new Person("SA") };//调用显示实现的泛型接口方法IEnumerable<Person> people = new People(peopleList);Console.WriteLine(" IEnumerable<Person>接口对象显示实现集合类迭代:");foreach (Person person in people){Console.Write($"{person.name},");}Console.WriteLine("\r\n");//调用隐式实现的接口方法People peo = new People(peopleList);Console.WriteLine("People集合类对象隐式实现集合对象迭代:");foreach (Person person in people){Console.Write($"{person.name},");}Console.ReadKey();}}//自定义集合类的元素类型public class Person{public string name { get; set; }public Person(string name){this.name = name;}}//自定义集合类public class People : IEnumerable<Person>{private List<Person> _p;public People() { }public People(List<Person> peo){_p = peo;}//隐式实现IEnumrable接口,如果集合类型是People,调用该迭代器实现方法public IEnumerator GetEnumerator(){//用yield return返回,其实yield内部就是实现了IEnumrator接口的三个成员.//不知道这么理解对否,逻辑上是这样的,这样就不用再额外写IEnumrator接口的三个成员代码实现了,代码调试OK,奈斯!!!for (int i = 0; i < _p.Count; i++){yield return _p[i];}}//显示实现IEnumrable<Person>接口,,如果集合类型是IEnumrable<Person>,调用该迭代器实现方法IEnumerator<Person> IEnumerable<Person>.GetEnumerator(){foreach (var item in _p){yield return item;}}}
}

代码执行后的结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/306106.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字证书在网络安全中的关键作用与日常应用

在当今数字化的时代&#xff0c;网络安全问题日益凸显&#xff0c;保护数据安全和用户隐私成为了人们关注的焦点。数字证书作为一种重要的网络安全技术&#xff0c;其在网络安全中扮演着关键的角色&#xff0c;并且在我们的日常生活中有着广泛的应用。现在给大家介绍简单介绍下…

一些优雅的算法(c++)

求最大公约数&#xff1a;辗转相除法 int gcd(int a,int b){return b0?a:gcd(b,a%b); }求最小公倍数&#xff1a;两整数之积除以最大公约数 int lcm(int a, int b){return a*b / gcd(a, b); }十进制转n进制&#xff1a; char get(int x){if(x<9){return x0;}else{return…

C#基础--之数据类型

C#基础–之数据类型 在第一章我们了解了C#的输入、输出语句后&#xff0c;我这一节主要是介绍C#的基础知识&#xff0c;本节的内容也是后续章节的基础&#xff0c;好的开端等于成功的一半。在你阅读完本章后&#xff0c;你就有足够的C#知识编写简单的程序了。但还不能使用封装、…

Docker 学习笔记(三):Centos7 中 Docker 使用,镜像、容器,以及操作等常用命令小结

一、前言 记录时间 [2024-4-7] 前置文章&#xff1a; Docker学习笔记&#xff08;一&#xff09;&#xff1a;入门篇&#xff0c;Docker概述、基本组成等&#xff0c;对Docker有一个初步的认识 Docker学习笔记&#xff08;二&#xff09;&#xff1a;在Linux中部署Docker&#…

重磅!Cloud Ace云一 荣获 2024 年 Google Cloud 年度合作伙伴两项大奖!

美国当地时间2024年4月8日&#xff0c;Google Cloud 官方在 Google Cloud Next24 颁奖典礼上宣布 Cloud Ace云一 获得 2024 年 Google Cloud 年度合作伙伴两项大奖&#xff1a; 大中华区年度最佳服务合作伙伴奖&#xff08;Services: Greater China&#xff09; 香港地区年度最…

java实现图片合成,图片嵌套,背景图片添加二维码

代码仓库:picture-synthesis: 使用Java操作图片合成功能&#xff0c;提供底图和二维码可生成对应的邀请码海报 我借鉴的一个小demo,包含生成二维码,操作多张图片合成,保存图片到本地,合成效果如下: 入口:

电工技术学习笔记——正弦交流电路

一、正弦交流电路 1. 正弦量的向量表示法 向量表示方法&#xff1a;正弦交流电路中&#xff0c;相量表示法是一种常用的方法&#xff0c;用于描述电压、电流及其相位关系。相量表示法将正弦交流信号表示为复数&#xff0c;通过复数的运算来描述电路中各种参数的相互关系 …

RAGFlow:基于OCR和文档解析的下一代 RAG 引擎

一、引言 在人工智能的浪潮中&#xff0c;检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;简称RAG&#xff09;技术以其独特的优势成为了研究和应用的热点。RAG技术通过结合大型语言模型&#xff08;LLMs&#xff09;的强大生成能力和高效的信息检索系统…

李沐27_含并行连结的网络GoogLeNet_Inception——自学笔记

Inception块 1.四个路径从不同层面抽取信息&#xff0c;然后在输出通道维合并。 2.有更少的参数个数和计算复杂度&#xff08;相比于3X3和5X5卷积层&#xff09; GoogLeNet 1.五个stages&#xff0c;九个inception块 Inception各种后续变种 1.Inception-BN(V2)——使用ba…

科技云报道:大模型加持后,数字人“更像人”了吗?

科技云报道原创。 北京冬奥运AI 虚拟人手语主播、杭州亚运会数字人点火、新华社数字记者、数字航天员小诤…当随着越来越多数字人出现在人们生活中&#xff0c;整个数字人行业也朝着多元化且广泛的应用方向发展&#xff0c;快速拓展到不同行业、不同场景。 面向C端&#xff0…

python+appium调@pytest.mark.parametrize返回missing 1 required positional argument:

出错描述&#xff1a; 1、在做pythonappium自动化测试时&#xff0c;使用装饰器pytest.mark.parametrize&#xff08;“参数”&#xff0c;[值1&#xff0c;值2&#xff0c;值3]&#xff09;&#xff0c;测试脚本执行返回test_xx() missing 1 required positional argument:“…

紫叶写作靠谱不 #笔记#学习方法#媒体

紫叶写作是一款非常好用的论文写作工具&#xff0c;它不仅提供了查重降重的功能&#xff0c;还能帮助用户快速完成论文的撰写和格式编辑。通过紫叶写作&#xff0c;用户可以轻松地查重降重&#xff0c;避免论文中出现抄袭和重复的现象&#xff0c;保证论文的原创性和质量。 紫叶…

【Java基础题型】题目 1020: 猴子吃桃的问题

猴子吃桃问题。猴子第一天摘下若干个桃子&#xff0c;当即吃了一半&#xff0c;还不过瘾&#xff0c;又多吃了一个。 第二天早上又将剩下的桃子吃掉一半&#xff0c;又多吃一个。 以后每天早上都吃了前一天剩下的一半零一个。 到第N天早上想再吃时&#xff0c;见只剩下一个桃子…

智能面试——录音及播放下载js-audio-recorder — post请求,formdata传参

录音插件 js-audio-recorder bug&#xff1a;本地调试调取不起来麦克风 浏览器配置安全域名 chrome://flags/Insecure origins treated as secure输入域名即可电脑需要连接上耳机 <template><div class"BaseRecorder"><div class"BaseRecorder-r…

React之基础项目搭建

前言 React的生态系统非常庞大&#xff0c;拥有大量的第三方库和工具&#xff0c;如React Native&#xff08;用于构建原生移动应用&#xff09;、Next.js&#xff08;用于构建服务器渲染应用&#xff09;、Create React App&#xff08;用于快速搭建React应用的脚手架&#x…

鸿蒙内核源码分析 (物理内存篇) | 怎么管理物理内存

如何初始化物理内存&#xff1f; 鸿蒙内核物理内存采用了段页式管理&#xff0c;先看两个主要结构体。结构体的每个成员变量的含义都已经注解出来&#xff0c;请结合源码理解. #define VM_LIST_ORDER_MAX 9 //伙伴算法分组数量&#xff0c;从 2^0&#xff0c;2^1&#…

【网络初识】网络相关概念详解

一.局域网VS广域网 局域网 局域网:Local Area Network~简称LAN.指在某一特定区域内由多台计算机组成的互联网组。局域网内的主机之间能方便的进行网络通信&#xff0c;又称为内网.局域网和局域网之间在没有连接的情况下&#xff0c;是无法通信的。局域网的组建方式: 基于网线…

新规来了!智能音视频技术重塑信贷体验

近日&#xff0c;国家金融监督管理总局发布《固定资产贷款管理办法》《流动资金贷款管理办法》《个人贷款管理办法》&#xff08;以下简称“三个办法”&#xff09;。 具体来看&#xff0c;新规明确了以下要求&#xff1a; 1、明确视频面签、电子签约要求 允许商业银行通过视…

【话题】AI技术创业有那些机会,简单探讨下

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景机会一、引言二、AI技术的创业机遇1.智能服务行业的兴起2.数据驱动的业务模式创新3.AI与产业融合的创新发展 三、AI技术创业的挑战1.技术门槛高2.法规政策的不确定性…

Java 中文官方教程 2022 版(三十四)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html 长期持久性 原文&#xff1a;docs.oracle.com/javase/tutorial/javabeans/advanced/longpersistence.html 长期持久性是一种模型&#xff0c;可以将 bean 保存为 XML 格式。 有关 XML 格式和如何为非 be…