Gewusst wie: Zugreifen auf Auflistungsklassen mit foreach (C#-Programmierhandbuch)

Aktualisiert: November 2007

Im folgenden Codebeispiel wird das Erstellen einer nicht generischen Auflistungsklasse veranschaulicht, die mit foreach verwendet werden kann. Die Klasse ist ein Zeichenfolgentokenizer und als solcher vergleichbar mit der C-Laufzeitfunktion strtok_s.

Hinweis:

Dieses Beispiel entspricht nur in den Fällen der empfohlenen Vorgehensweise, in denen keine generische Auflistungsklasse verwendet werden kann. Generische Typen werden in C# und .NET Framework, Version 2.0 und höher, unterstützt. Ein Beispiel für die Implementierung einer typsicheren generischen Auflistungsklasse, die IEnumerable<T>unterstützt und auf diese Weise die nachfolgend erörterten Probleme vermeidet, finden Sie unter Gewusst wie: Erstellen von Iteratorblöcken für generische Listen (C#-Programmierhandbuch).

Im folgenden Beispiel löst Tokens den Satz "This is a sample sentence." in Tokens auf (mit ' ' und '-' als Trennzeichen) und listet diese Tokens mit der foreach-Anweisung auf:

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

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

Tokens verwendet intern ein Array, das IEnumerator und IEnumerable selbst implementiert. Im Codebeispiel hätten die Enumerationsmethoden des Arrays auch als eigene Methoden verwendet werden können. Dies hätte jedoch nicht dem Zweck dieses Beispiels entsprochen.

In C# ist es nicht zwingend erforderlich, dass eine Auflistungsklasse von IEnumerable und IEnumerator erbt, um kompatibel mit foreach zu sein. Solange die Klasse über die erforderlichen Member GetEnumerator, MoveNext, Reset und Current verfügt, funktioniert sie mit foreach. Wenn Sie die Schnittstellen weglassen, hat dies den Vorteil, dass Sie den Rückgabetyp Current definieren können. So können Sie genauer sein als bei Verwendung von Object und gewährleisten zusätzlich noch Typsicherheit.

Ändern Sie ausgehend vom obigen Codebeispiel z. B. die folgenden Zeilen:

// 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  

Da Current eine Zeichenfolge zurückgibt, erkennt der Compiler, wenn in einer foreach-Anweisung ein nicht kompatibler Typ verwendet wird:

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

Der Nachteil beim Weglassen von IEnumerable und IEnumerator besteht darin, dass die Auflistungsklasse nicht mehr mit den foreach-Anweisungen oder Entsprechungen anderer Common Language Runtime-kompatibler Sprachen verwendet werden kann.

Sie können die Vorteile beider Ansätze (d. h. Typsicherheit innerhalb von C# und Interoperabilität mit anderen Common Language Runtime-kompatiblen Sprachen) nutzen, indem Sie von IEnumerable und IEnumerator erben und wie im folgenden Beispiel die explizite Schnittstellenimplementierung verwenden.

Beispiel

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.  
*/

Siehe auch

Konzepte

C#-Programmierhandbuch

Referenz

Arrays (C#-Programmierhandbuch)

Auflistungsklassen (C#-Programmierhandbuch)

System.Collections.Generic

Weitere Ressourcen

C#-Referenz