HOW TO:使用 foreach 存取集合類別 (C# 程式設計手冊)

更新:2011 年 3 月

下列程式碼範例說明如何撰寫可搭配 foreach 使用的非泛型集合類別。 此範例會定義從字串中取出語彙基元的類別。

注意事項注意事項

此範例所呈現的建議作法,只適用於無法使用泛型集合類別的情況。 如需如何實作支援 IEnumerable<T> 之型別安全泛型集合類別的範例,請參閱 HOW TO:建立泛型清單的 Iterator 區塊 (C# 程式設計手冊)

在範例中,下列程式碼區段會使用 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 類別會在內部使用陣列儲存語彙基元。 由於陣列會實作 IEnumeratorIEnumerable,因此這個程式碼範例可能使用了陣列的列舉方法 (GetEnumeratorMoveNextResetCurrent),而不是在 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# 中,集合類別不一定要實作 IEnumerableIEnumerator,也能與 foreach 相容。 如果類別具有必要的 GetEnumeratorMoveNextResetCurrent 成員,就可以搭配 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)  

省略 IEnumerableIEnumerator 的缺點是,集合類別不再能夠與其他 Common Language Runtime 語言的 foreach 陳述式 (或對等陳述式) 交互作用。

請參閱

參考

陣列 (C# 程式設計手冊)

集合類別 (C# 程式設計手冊)

System.Collections.Generic

概念

C# 程式設計手冊

其他資源

C# 參考

變更記錄

日期

記錄

原因

2011 年 3 月

已修訂讓說明更清楚。

資訊加強。