C#笔记——5.迭代器
迭代器(Iterator)简介:
设计模式中的迭代器模式,分离集合对象的遍历行为,抽象出迭代器负责,来做到既不暴露集合的内部结构,又可以让外部代码透明的访问集合内部的数据。
因为迭代器模式应用非常普遍,所以各种编程语言都对迭代器模式进行了封装。
.Net的迭代器模式
IEnumerable接口:
public interface IEnumerable{
IEnumerator GetEnumerator();
}
实现了IEnumerable接口的集合表明该集合能够提供一个Enumerator(枚举器)对象,支持当前的遍历集合。该接口只有一个GetEnumerator()成员方法。
IEnumerator接口:
public interface IEnumerator{
object Current{
get;
}
bool MoveNext();
void Reset();
}
MoveNext()方法调整遍历指针移向集合的下一个元素。注意,遍历指针的初始位置是集合中第一个元素的前面。要指向第一个元素,必须先调用一次
MoveNext()方法。该方法返回一个布尔值,如果成功遍历到下一个元素,则返回true;如果指针移出末尾,则返回false。
Reset()方法用于设置遍历指针指向初始位置,即集合中第一个元素的前面。
Current属性返回集合中当前对象的引用。
IEnumerable和IEnumerator的区别:
1、一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方式返回IEnumerator object)。
2、IEnumerator object具体实现了迭代器(通过MoveNext(),Reset(),Current)。
3、从这两个接口的用词选择上,也可以看出其不同:IEnumerable是一个声明式的接口,声明实现该接口的class是“可枚举(enumerable)”的,但并没有说明如何实现枚举器(iterator);IEnumerator是一个实现式的接口,IEnumerator object就是一个iterator。
4、IEnumerable和IEnumerator通过IEnumerable的GetEnumerator()方法建立了连接,client可以通过IEnumerable的GetEnumerator()得到IEnumerator object,在这个意义上,将GetEnumerator()看作IEnumerator object的factory method也未尝不可。
.Net的迭代器实现
对一个自定义的类实现IEnumerable接口示例代码:
/// <summary>
/// The Class Which We Want To Implement the IEnumerable interface.
/// </summary>
public class UserData : IEnumerable
{
public List<Person> UsersList { get; set; }
public UserData() { }
public UserData(List<Person> list) => UsersList = list;
//Implementation The Interface`s GetEnumerable method
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
//Class method
public PersonEnum GetEnumerator()
{
return new PersonEnum(UsersList);
}
}
/// <summary>
/// The Class We Should Also Implement The IEnumerator Interface ,When We Want To Implement The IEnumerable Interface.
/// </summary>
public class PersonEnum : IEnumerator
{
public List<Person> _pList;
//Mark The Position Of The Current Element.
int pos = -1;
public PersonEnum(List<Person> list)
{
_pList = list;
}
//The Core Of The IEnumerator
object IEnumerator.Current
{
get
{
return Current;
}
}
//The Class Mathod
public Person Current
{
get
{
try
{
return _pList[pos];
}
catch(IndexOutOfRangeException)
{
throw new IndexOutOfRangeException();
}
}
}
public bool MoveNext()
{
pos++;
return (pos < _pList.Count);
}
public void Reset()
{
pos = -1;
}
}
在UserData类实现了IEnumerable接口之后,我们便可以使用foreach来进行迭代访问了
class Program
{
private const string filePath = "UserList.json";
static void Main(string[] args)
{
using (StreamReader streamReader = File.OpenText(filePath))
{
string str = streamReader.ReadToEnd();
UserData u = JsonMapper.ToObject<UserData>(str);
//Implement the IEnumerable in the Class UserData To Support the use of foreach.
foreach (Person p in u)
{
Console.WriteLine(p.ToString());
}
}
Console.ReadKey();
}
}
使用的简单类代码(可忽略,重点是上方IEnumerable接口的实现代码):
[ProtoContract]
[ProtoInclude(5, typeof(Developer))]
[ProtoInclude(6, typeof(Designer))]
public class Person
{
[ProtoMember(1)]
public String Name { get; set; }
[ProtoMember(2)]
public String ID { get; set; }
[ProtoMember(3)]
public bool Gender { get; set; }
[ProtoMember(4)]
public int Age { get; set; }
public Person(string name, string id, bool gender, int age)
{
Name = name;
ID = id;
Gender = gender;
Age = age;
}
public Person() { }
public override string ToString()
{
return "Name : " + Name + ", ID : " + ID + " , Gender :" + Gender + " , Age : " + Age;
}
}
[ProtoContract]
public class Developer : Person
{
[ProtoMember(1)]
public String Languages { get; set; }
public Developer(string name, string id, bool gender, int age, string language) : base(name, id, gender, age)
{
Languages = language;
}
public Developer() : base() { }
public override string ToString()
{
return base.ToString() + " , Work with the languages : " + Languages + " .";
}
}
[ProtoContract]
public class Designer : Person
{
[ProtoMember(1)]
public string Software { get; set; }
public Designer(string name, string id, bool gender, int age, string software) : base(name, id, gender, age)
{
Software = software;
}
public Designer() : base() { }
public override string ToString()
{
return base.ToString() + ", Work with software : " + Software + " .";
}
}
REF
深入理解C#、C#高级编程、C#游戏脚本编程