共用方式為


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

更新:2007 年 11 月

下列程式碼範例說明如何撰寫可搭配 foreach 使用的非泛型集合類別。這是一個從字串中取出語彙基元的類別,類似於 C 執行階段函式 strtok_s。

注意事項:

此範例所呈現的建議作法,只適用於無法使用泛型集合類別的情況。在 C# 語言和 .NET Framework 的 2.0 (含) 以後版本中有支援泛型。如需如何實作支援 IEnumerable<T> 之型別安全泛型集合類別的範例,藉此避免本主題稍後討論的問題,請參閱 HOW TO:建立泛型清單的 Iterator 區塊 (C# 程式設計手冊)

在下列範例中,Tokens 會將 "This is a sample sentence." 這個句子分成多個語彙基元 (使用 ' ' 和 '-' 做為分隔符號),並以 foreach 陳述式列舉這些語彙基元:

Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});

foreach (string item in f)
{
    System.Console.WriteLine(item);
}

Tokens 在內部使用一個陣列,此陣列本身實作 IEnumeratorIEnumerable。這個程式碼範例也可以使用陣列的列舉方法當做本身的方法,但這樣會失去此範例的目的。

在 C# 中,集合類別不一定需要繼承自 IEnumerableIEnumerator,才能與 foreach 相容。只要類別具有必要的 GetEnumeratorMoveNextResetCurrent 成員,就可以使用 foreach。省略介面的優點是,您可以將 Current 的傳回型別定義得比 Object 更明確,進而提供型別安全。

例如,從本主題前面的範例程式碼開始,變更下列幾行:

// No longer inherits from IEnumerable:
public class Tokens  
// Doesn't return an IEnumerator:
public TokenEnumerator GetEnumerator()  
// No longer inherits from IEnumerator:
public class TokenEnumerator  
// Type-safe: returns string, not object:
public string Current  

這時由於 Current 傳回的是字串,所以當 foreach 陳述式中使用了不相容的型別時,編譯器便可偵測出來:

// Error: cannot convert string to int:
foreach (int item in f)  

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

您可以藉由繼承自 IEnumerableIEnumerator,並使用明確介面實作,以此結合兩者的優點,不但可有 C# 中的型別安全,又能與其他 Common Language Runtime 相容語言互通,如下範例。

範例

using System.Collections;

// Declare the Tokens class:
public class Tokens : IEnumerable
{
    private string[] elements;

    Tokens(string source, char[] delimiters)
    {
        // Parse the string into tokens:
        elements = source.Split(delimiters);
    }

    // IEnumerable Interface Implementation:
    //   Declaration of the GetEnumerator() method 
    //   required by IEnumerable
    public IEnumerator GetEnumerator()
    {
        return new TokenEnumerator(this);
    }


    // Inner class implements IEnumerator interface:
    private class TokenEnumerator : IEnumerator
    {
        private int position = -1;
        private Tokens t;

        public TokenEnumerator(Tokens t)
        {
            this.t = t;
        }

        // Declare the MoveNext method required by IEnumerator:
        public bool MoveNext()
        {
            if (position < t.elements.Length - 1)
            {
                position++;
                return true;
            }
            else
            {
                return false;
            }
        }

        // Declare the Reset method required by IEnumerator:
        public void Reset()
        {
            position = -1;
        }

        // Declare the Current property required by IEnumerator:
        public object Current
        {
            get
            {
                return t.elements[position];
            }
        }
    }


    // Test Tokens, TokenEnumerator
    static void Main()
    {
        // Testing Tokens by breaking the string into tokens:
        Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});

        foreach (string item in f)
        {
            System.Console.WriteLine(item);
        }
    }
}
/* Output:
    This
    is
    a
    sample
    sentence.  
*/

請參閱

概念

C# 程式設計手冊

參考

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

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

System.Collections.Generic

其他資源

C# 參考