次の方法で共有


方法 : foreach を使用してコレクション クラスにアクセスする (C# プログラミング ガイド)

更新 : 2011 年 3 月

次のコード例では、foreach と共に使用できる非ジェネリック コレクション クラスの記述方法を示します。 この例では、文字列のトークナイザ クラスを定義しています。

注意

この例では、ジェネリック コレクション クラスを使用できない場合にのみ推奨される方法を示します。 IEnumerable<T> をサポートするタイプ セーフのジェネリック コレクション クラスを実装する方法の例については、「方法: ジェネリック リストの反復子ブロックを作成する (C# プログラミング ガイド)」を参照してください。

この例の次のコード セグメントでは、区切り記号として ' ' と '-' を使用して "This is a sample sentence." という文をトークンに分割する Tokens クラスを使用しています。 コードでは、これらのトークンを表示するために 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 を実装しているため、このコード例では Tokens クラスでこれらを定義するのではなく、配列の列挙型メソッド (GetEnumeratorMoveNextReset、および Current) を使用することもできました。 この例にメソッド定義が含まれているのは、メソッドを定義する方法と各メソッドの動作を明確にするためです。

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# では、foreach と互換性を保つために、コレクション クラスで IEnumerableIEnumerator を実装する必要はありません。 必須の GetEnumeratorMoveNextReset、および 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)  

IEnumerableIEnumerator を省略すると、コレクション クラスを他の共通言語ランタイム言語の foreach ステートメント (または同等のステートメント) と相互運用できなくなるので注意が必要です。

参照

参照

配列 (C# プログラミング ガイド)

コレクション クラス (C# プログラミング ガイド)

System.Collections.Generic

概念

C# プログラミング ガイド

その他の技術情報

C# リファレンス

履歴の変更

日付

履歴

理由

2011 年 3 月

より明確になるように変更。

情報の拡充