HOW TO:使用 foreach 存取集合類別 (C# 程式設計手冊)
下列程式碼範例說明如何撰寫可搭配 foreach 使用的非泛型集合類別。 此範例會定義從字串中取出語彙基元的類別。
注意事項 |
---|
此範例所呈現的建議作法,只適用於無法使用泛型集合類別的情況。如需如何實作支援 IEnumerable<T> 之型別安全泛型集合類別的範例,請參閱 Iterator (C# 和 Visual Basic)。 |
在範例中,下列程式碼區段會使用 Tokens 類別將 "This is a sample sentence." 這個句子分成多個語彙基元 (使用 ' ' 和 '-' 做為分隔符號)。 然後程式碼會使用 foreach 陳述式顯示這些語彙基元。
Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});
// Display the tokens.
foreach (string item in f)
{
System.Console.WriteLine(item);
}
範例
Tokens 類別會在內部使用陣列儲存語彙基元。 由於陣列會實作 IEnumerator 和 IEnumerable,因此這個程式碼範例可能使用了陣列的列舉方法 (GetEnumerator、MoveNext、Reset 和 Current),而不是在 Tokens 類別中定義這些方法。 範例中會包含方法定義,用以釐清其定義方式及各自的功能。
using System.Collections;
// Declare the Tokens class. The class implements the IEnumerable interface.
public class Tokens : IEnumerable
{
private string[] elements;
Tokens(string source, char[] delimiters)
{
// The constructor parses the string argument into tokens.
elements = source.Split(delimiters);
}
// The IEnumerable interface requires implementation of method GetEnumerator.
public IEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
}
// Declare an inner class that implements the IEnumerator interface.
private class TokenEnumerator : IEnumerator
{
private int position = -1;
private Tokens t;
public TokenEnumerator(Tokens t)
{
this.t = t;
}
// The IEnumerator interface requires a MoveNext method.
public bool MoveNext()
{
if (position < t.elements.Length - 1)
{
position++;
return true;
}
else
{
return false;
}
}
// The IEnumerator interface requires a Reset method.
public void Reset()
{
position = -1;
}
// The IEnumerator interface requires a Current method.
public object Current
{
get
{
return t.elements[position];
}
}
}
// Test the Tokens class.
static void Main()
{
// Create a Tokens instance.
Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});
// Display the tokens.
foreach (string item in f)
{
System.Console.WriteLine(item);
}
}
}
/* Output:
This
is
a
sample
sentence.
*/
在 C# 中,集合類別不一定要實作 IEnumerable 和 IEnumerator,也能與 foreach 相容。 如果類別具有必要的 GetEnumerator、MoveNext、Reset 和 Current 成員,就可以搭配 foreach 使用。 省略介面的優點是,您可以為 Current 定義比 Object 更明確的傳回型別。 這樣就能提供型別安全。
例如,變更上述範例中的下列幾行。
// Change the Tokens class so that it no longer implements IEnumerable.
public class Tokens
{
// . . .
// Change the return type for the GetEnumerator method.
public TokenEnumerator GetEnumerator()
{ }
// Change TokenEnumerator so that it no longer implements IEnumerator.
public class TokenEnumerator
{
// . . .
// Change the return type of method Current to string.
public string Current
{ }
}
}
由於 Current 傳回字串,因此當 foreach 陳述式中使用了不相容的型別時,編譯器便可偵測出來,如下列程式碼中所示。
// Error: Cannot convert type string to int.
foreach (int item in f)
省略 IEnumerable 和 IEnumerator 的缺點是,集合類別不再能夠與其他 Common Language Runtime 語言的 foreach 陳述式 (或對等陳述式) 交互作用。