.Net学习难点讨论系列11 - foreach与迭代器

来源:互联网 发布:走地分析软件 编辑:程序博客网 时间:2024/05/16 10:35

(本文主要整理于ASP.NET2.0开发指南部分内容)

在.NET 1.1中要使一个自定义的集合类可以与foreach一起工作,我们需要实现IEnumerable接口的GetEnumerator方法。该数据集合中的元素需要实现IEnumerator接口。我们直接看下面这个例子:

public class Persons : IEnumerable

{

public string[] m_Names;

public Persons(params string[] Names)

{

m_Names = new string[Names.Length];

Names.CopyTo(m_Names, 0);

}

 

//实现索引器

public string this[int index]

{

get

{

return m_Names[index];

}

set

{

m_Names[index] = value;

}

}

 

//实现IEnumerable成员

//需返回一个IEnumerator类型的对象

#region IEnumerable 成员

 

IEnumerator IEnumerable.GetEnumerator()

{

return new PersonsEnumerator(this);

}

 

#endregion

}

 

public class PersonsEnumerator : IEnumerator

{

int index = -1;

Persons P;

public PersonsEnumerator(Persons P)

{

this.P = P;

}

 

#region IEnumerator 成员

 

object IEnumerator.Current

{

get

{

return P.m_Names[index];

}

}

 

bool IEnumerator.MoveNext()

{

int tempIndex = ++index;

if (tempIndex >= P.m_Names.Length)

{

return false;

}

else

{

return true;

}

}

 

void IEnumerator.Reset()

{

index = -1;

}

#endregion

}

使用(非泛型)迭代器的方式:

static void Main()

{

Persons arrPersons = new Persons("Michel", "Rebecca", "Polaris");

foreach (string s in arrPersons)

{

Console.WriteLine(s);

}

}

 

在C# 2.0中我们可以通过新增的关键字 – yeild,来方便的实现一个迭代器。而且.NET2.0中新增的泛型可以使迭代器强类型化。

一步步进行:首先我们将上述程序改写为用yield关键字实现(仍然是非泛型)。

public class Persons : IEnumerable

{

public string[] m_Names;

public Persons(params string[] Names)

{

m_Names = new string[Names.Length];

Names.CopyTo(m_Names, 0);

}

 

#region IEnumerable 成员

 

IEnumerator IEnumerable.GetEnumerator()

{

for (int i = 0; i < m_Names.Length; i++)

{

yield return m_Names[i];

}

}

 

#endregion

}

 

接下来,我们将此方法改写为泛型的实现:

public class Persons<T> : IEnumerable<T>

{

public T[] m_Names;

public Persons(params T[] Names)

{

m_Names = new T[Names.Length];

Names.CopyTo(m_Names, 0);

}

 

#region IEnumerable<T> 成员

 

IEnumerator<T> IEnumerable<T>.GetEnumerator()

{

for (int i = 0; i < m_Names.Length; i++)

{

yield return m_Names[i];

}

}

 

#endregion

}

泛型版迭代器的使用:

static void Main()

{

Persons<string> arrPersons = new Persons<string>("Michel", "Rebecca", "Polaris");

foreach (string s in arrPersons)

{

Console.WriteLine(s);

}

}

上文基本列出了怎样使用yield实现一个迭代器。

下面来说一下yield的一些使用方式:

1. 终止yield迭代的方式

IEnumerator IEnumerable.GetEnumerator()

{

for (int i = 0; i < m_Names.Length; i++)

{

yield return m_Names[i];

if (i >= 1)

{

yield break;

}

}

}

2. 逆序迭代内容

IEnumerator IEnumerable.GetEnumerator()

{

for (int i = (m_Names.Length - 1); i >= 0; --i)

{

yield return m_Names[i];

}

}

3. 迭代器的另一种实现,返回实现IEnumerable<T>接口的对象,不实现GetEnumerator()方法。

public class Persons<T>

{

private T[] m_Names;

public Persons(params T[] Names)

{

m_Names = new T[Names.Length];

Names.CopyTo(m_Names, 0);

}

 

public IEnumerable<T> GetPersons()

{

for (int i = 0; i < m_Names.Length; i++)

{

yield return m_Names[i];

}

}

}

 

class Program

{

static void Main()

{

Persons<string> arrPersons = new Persons<string>("Michel", "Rebecca", "Polaris");

foreach (string s in arrPersons.GetPersons())

{

Console.WriteLine(s);

}

}

}

原创粉丝点击