我们知道数组对象可以使用foreach迭代进行遍历,同时我们发现类ArrayList和List也可以使用foreach进行迭代。如果我们自己编写的类也需要使用foreach进行迭代时该怎么办呢?
IEnumerable:
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
如果自己编写的类需要foreach进行迭代就需要实现IEnumerable接口,表示当前的类可以进行迭代。
我们发现该接口唯一的方法返回的是另一个接口IEnumerator,下面看看这个接口是干嘛的。
IEnumerator:
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
如果说IEnumerable接口是表示当前类可以进行迭代,那么IEnumerator则是实现迭代逻辑的接口,我们需要编写一个实现IEnumerator接口的类并在其中编写好迭代逻辑。
下面直接上一个例子:
People.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
/// <summary>
/// 自定义的可迭代类.
/// </summary>
class People : IEnumerable<Person>
{
//这里用了一个 List 有点无聊, 因为 List 本身就可以进行迭代, 为了写例子没办法
private List<Person> _list; public People()
{
_list = new List<Person>();
} public IEnumerator<Person> GetEnumerator()
{
return new PeopleEnumerator(_list.ToArray());
} //示例程序所以这里就添加一个方法就行了
public void AddPerson(Person person)
{
_list.Add(person);
} System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
} /// <summary>
/// 迭代器的逻辑实现类.
/// </summary>
class PeopleEnumerator : IEnumerator<Person>
{
public Person[] pers; private int index = -; public PeopleEnumerator(Person[] pers)
{
this.pers = pers;
} public Person Current
{
get
{
return pers[index];
}
} public bool MoveNext()
{
index++;
return index < pers.Length;
} public void Reset()
{
index = -;
} public void Dispose()
{
pers = null;
} object System.Collections.IEnumerator.Current
{
get { return Current; }
}
} /// <summary>
/// 集合的元素.
/// </summary>
class Person
{
public string name;
public bool isMale; public Person(string name, bool isMale)
{
this.name = name;
this.isMale = isMale;
}
}
}
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
static void Main(string[] args)
{
new Program(); Console.ReadKey();
} public Program()
{
People people = new People();
people.AddPerson(new Person("tony", true));
people.AddPerson(new Person("tony mom", false));
people.AddPerson(new Person("alen", true));
people.AddPerson(new Person("gilbret", true));
people.AddPerson(new Person("mark", false)); foreach(Person person in people)
{
Console.WriteLine("Name: {0}, sex is male:{1}", person.name, person.isMale);
}
}
}
}
下面是运行结果:
Name: tony, sex is male:True
Name: tony mom, sex is male:False
Name: alen, sex is male:True
Name: gilbret, sex is male:True
Name: mark, sex is male:False
yield:
yield 是 C# 提供的一个特殊的用于迭代的语法,其可以简化迭代实现的代码,yield return 语句返回集合的一个元素,并移动到下一个元素上,yield break 可以停止迭代。
头晕了吧?没关系,我们先看看一个简单的例子:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
static void Main(string[] args)
{
new Program(); Console.ReadKey();
} public Program()
{
People people = new People(); foreach(string name in people)
{
Console.WriteLine(name);
}
}
} class People : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield return "gilbert";
yield return "alen";
yield return "grace";
}
}
}
运行的结果为:
gilbert
alen
grace
没错,当程序碰到yield return这个语句时就将其后面附带的数据作为current返回,同时程序会再此处暂停,运行结束foreach中的代码后再继续,同时执行的是下一个语句了,我们再看看yield break的效果,该效果表示立即停止迭代,示例如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Test
{
class Program
{
static void Main(string[] args)
{
new Program(); Console.ReadKey();
} public Program()
{
People people = new People(); foreach(string name in people)
{
Console.WriteLine(name);
}
}
} class People : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield return "gilbert";
yield return "alen";
yield break;//指示这里要停止迭代
yield return "grace";
}
}
}
运行的结果为:
gilbert
alen
最后要说一下:包含yoeld语句的方法或者属性也称为迭代块,迭代块必须声明为返回IEnumerator或IEnumerable接口,迭代块可以包含多个yield return或yield break语句,但是不能包含return语句。
不要小看yield迭代快,下一篇笔记我要可转回U3D了,我们要详细的看看yield在U3D里的变种——协程。
IEnumerable、IEnumerator与yield的学习的更多相关文章
-
ICollection IEnumerable/IEnumerator IDictionaryEnumerator yield
Enumerable和IEnumerator接口是.NET中非常重要的接口,二者区别: 1. IEnumerable是个声明式的接口,声明实现该接口的类就是“可迭代的enumerable”,但并没用说 ...
-
C# ~ 从 IEnumerable / IEnumerator 到 IEnumerable<;T>; / IEnumerator<;T>; 到 yield
IEnumerable / IEnumerator 首先,IEnumerable / IEnumerator 接口定义如下: public interface IEnumerable /// 可枚举接 ...
-
IEnumerable, IEnumerator接口
IEnumerable接口 // Exposes the enumerator, which supports a simple iteration over a non-generic collec ...
-
[原译]实现IEnumerable接口&;理解yield关键字
原文:[原译]实现IEnumerable接口&理解yield关键字 著作权声明:本文由http://leaver.me 翻译,欢迎转载分享.请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢 ...
-
[Python 学习]2.5版yield之学习心得 - limodou的学习记录 - limodou是一个程序员,他关心的焦点是Python, DocBook, Open Source …
[Python 学习]2.5版yield之学习心得 - limodou的学习记录 - limodou是一个程序员,他关心的焦点是Python, DocBook, Open Source - [Pyth ...
-
c#yield,IEnumerable,IEnumerator
foreach 在编译成IL后,实际代码如下: 即:foreach实际上是先调用可枚举对象的GetEnumerator方法,得到一个Enumerator对象,然后对Enumerator进行while循 ...
-
【Unity|C#】基础篇(20)——枚举器与迭代器(IEnumerable/IEnumerator)
[学习资料] <C#图解教程>(第18章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...
-
转-[Python 学习]2.5版yield之学习心得
在 shhgs 发布了关于< Py 2.5 what’s new 之 yield>之后,原来我不是特别关注 yield 的用法,因为对于2.3中加入的yield相对来说功能简单,它是作为一 ...
-
IEnumerable &; IEnumerator
IEnumerable 只有一个方法:IEnumerator GetEnumerator(). INumerable 是集合应该实现的一个接口,这样,就能用 foreach 来遍历这个集合. IEnu ...
随机推荐
-
Spring 整合 Redis
http://blog.csdn.net/java2000_wl/article/details/8543203/ pom构建: <modelVersion>4.0.0</model ...
-
Swift函数编程之Map、Filter、Reduce
在Swift语言中使用Map.Filter.Reduce对Array.Dictionary等集合类型(collection type)进行操作可能对一部分人来说还不是那么的习惯.对于没有接触过函数式编 ...
-
mybatis配置文件(其中,注意节点先后顺序)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC & ...
-
Winform 基础知识 之文件夹操作
using System.IO; /// <summary> /// 删除文件夹下所有文件 /// </summary> /// <param name="di ...
-
ASP.NET - 获得客户端的 IP 地址
通常我们都通过下面的代码获得IP: REMOTE_ADDR 说明:访问客户端的 IP 地址. 此项信息用户不可以修改.如果真的给改了的话,你也和服务器连接不了了,服务器就是按照这个来与客户端建立连接并 ...
-
chapter11_2 Lua链表与队列
链表 由于table是动态的实体,所以在Lua中实现链表是很方便的.每个节点以一个table来表示,一个“链表”只是节点table中的一个字段. 该字段包含了对其他table的引用.例如,要实现一个基 ...
-
Advanced Sort Algorithms
1. Merge Sort public class Mergesort { private int[] numbers; private int[] helper; private int numb ...
-
转载 Flask中客户端 - 服务器 - web应用程序 是如何处理request生成response的?
文章转载自https://blog.csdn.net/weixin_37923128/article/details/80992645 , 感谢原作者 当客户端向服务器发送一个请求时,服务器会将请求转 ...
-
用tkinter制作签名设计窗口
效果如下: from tkinter import * from tkinter import messagebox import requests import re from PIL import ...
-
弹性盒子 flexbox 元素居中
1 .navtext{ width:800px; height:600px; border: 1px solid black; justify-content:center; align-items: ...