(本文主要整理於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);
}
}
}