.Net學習難點討論系列11 - foreach與迭代器

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

}

}

}

發佈了1 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章