Exemplarische Vorgehensweise: Implementieren von IEnumerable(Of T) in Visual Basic

Die IEnumerable<T>-Schnittstelle wird durch Klassen implementiert, die eine Sequenz von Werten (jeweils ein Element nach dem anderen) zurückgeben können. Der Vorteil der Rückgabe einzelner Daten besteht darin, dass Sie nicht den gesamten Datensatz in den Speicher laden müssen, um mit ihm zu arbeiten. Sie müssen nur über genügend Arbeitsspeicher verfügen, um ein einziges Element aus den Daten zu laden. Klassen, die die IEnumerable(T)-Schnittstelle implementieren, können mit For Each-Schleifen oder LINQ-Abfragen verwendet werden.

Betrachten Sie beispielsweise eine Anwendung, die eine große Textdatei lesen und jede Zeile aus der Datei zurückgeben muss, die bestimmten Suchkriterien entspricht. Die Anwendung verwendet eine LINQ-Abfrage, um Zeilen aus der Datei zurückzugeben, die den angegebenen Kriterien entsprechen. Um den Inhalt der Datei mithilfe einer LINQ-Abfrage abzufragen, kann die Anwendung den Inhalt der Datei in ein Array oder eine Sammlung laden. Das Laden der gesamten Datei in ein Array oder eine Sammlung würde jedoch viel mehr Arbeitsspeicher verbrauchen, als erforderlich ist. Die LINQ-Abfrage könnte stattdessen den Dateiinhalt mithilfe einer aufzählbaren Klasse abfragen und nur Werte zurückgeben, die den Suchkriterien entsprechen. Abfragen, die nur wenige übereinstimmende Werte zurückgeben, würden viel weniger Arbeitsspeicher beanspruchen.

Sie können eine Klasse erstellen, die die IEnumerable<T>-Schnittstelle implementiert, um Quelldaten als aufzählbare Daten verfügbar zu machen. Ihre Klasse, die die IEnumerable(T)-Schnittstelle implementiert, erfordert eine weitere Klasse, die die IEnumerator<T>-Schnittstelle implementiert, um die Quelldaten zu durchlaufen. Diese beiden Klassen ermöglichen die sequenzielle Rückgabe von Datenelementen eines bestimmten Typs.

In dieser exemplarischen Vorgehensweise wird veranschaulicht, wie eine Klasse zum Erstellen der Schnittstelle IEnumerable(Of String) und eine Klasse zum Erstellen der Schnittstelle IEnumerator(Of String) erstellt wird, um eine Textdatei zeilenweise zu lesen.

Hinweis

Auf Ihrem Computer werden möglicherweise andere Namen oder Speicherorte für die Benutzeroberflächenelemente von Visual Studio angezeigt als die in den folgenden Anweisungen aufgeführten. Diese Elemente sind von der jeweiligen Visual Studio-Version und den verwendeten Einstellungen abhängig. Weitere Informationen finden Sie unter Personalisieren der IDE.

Erstellen der aufzählbaren Klasse

Erstellen des aufzählbaren Klassenprojekts

  1. Zeigen Sie in Visual Basic im Menü Datei auf Neu, und klicken Sie dann auf Projekt.

  2. Überprüfen Sie, ob im Dialogfeld Neues Projekt im Bereich Projekttypen der Eintrag Windows ausgewählt ist. Wählen Sie im Bereich Vorlagen die Option Klassenbibliothek aus. Geben Sie im Feld Name die Bezeichnung StreamReaderEnumerable ein, und klicken Sie dann auf OK. Das neue Projekt wird angezeigt.

  3. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Datei „Class1.vb“, und klicken Sie auf Umbenennen. Benennen Sie die Datei in StreamReaderEnumerable.vb um, und drücken Sie die EINGABETASTE. Durch Umbenennen der Datei wird die Klasse ebenfalls in StreamReaderEnumerable umbenannt. Diese Klasse implementiert die IEnumerable(Of String)-Schnittstelle.

  4. Klicken Sie mit der rechten Maustaste auf das Projekt StreamReaderEnumerable, zeigen Sie auf Hinzufügen, und klicken Sie dann auf Neues Element. Wählen Sie die Class-Vorlage aus. Geben Sie im Feld NameStreamReaderEnumerator.vb ein, und klicken Sie auf OK.

Die erste Klasse in diesem Projekt ist die aufzählbare Klasse. Sie implementiert die IEnumerable(Of String)-Schnittstelle. Diese generische Schnittstelle implementiert die IEnumerable-Schnittstelle und garantiert, dass Consumer dieser Klasse auf Werte zugreifen können, die als String typisiert sind.

Hinzufügen des Codes zum Implementieren von IEnumerable

  1. Öffnen Sie die Datei „StreamReaderEnumerable.vb“.

  2. Geben Sie in der Zeile nach Public Class StreamReaderEnumerable Folgendes ein, und drücken Sie die EINGABETASTE.

    Implements IEnumerable(Of String)
    

    Visual Basic füllt die Klasse automatisch mit den Membern auf, die für die IEnumerable(Of String)-Schnittstelle erforderlich sind.

  3. Diese aufzählbare Klasse liest nacheinander Zeilen aus einer Textdatei. Fügen Sie der Klasse den folgenden Code hinzu, um einen öffentlichen Konstruktor verfügbar zu machen, der einen Dateipfad als Eingabeparameter annimmt.

    Private _filePath As String
    
    Public Sub New(ByVal filePath As String)
        _filePath = filePath
    End Sub
    
  4. Die Implementierung der GetEnumerator-Methode der IEnumerable(Of String)-Schnittstelle gibt eine neue Instanz der StreamReaderEnumerator-Klasse zurück. Die Implementierung der GetEnumerator-Methode der IEnumerable-Schnittstelle kann Private vorgenommen werden, weil Sie nur Member der IEnumerable(Of String)-Schnittstelle verfügbar machen müssen. Ersetzen Sie den Code, den Visual Basic für die GetEnumerator-Methoden generiert hat, durch den folgenden Code.

    Public Function GetEnumerator() As IEnumerator(Of String) _
        Implements IEnumerable(Of String).GetEnumerator
    
        Return New StreamReaderEnumerator(_filePath)
    End Function
    
    Private Function GetEnumerator1() As IEnumerator _
        Implements IEnumerable.GetEnumerator
    
        Return Me.GetEnumerator()
    End Function
    

Hinzufügen des Codes zum Implementieren von IEnumerator

  1. Öffnen Sie die Datei „StreamReaderEnumerator.vb“.

  2. Geben Sie in der Zeile nach Public Class StreamReaderEnumerator Folgendes ein, und drücken Sie die EINGABETASTE.

    Implements IEnumerator(Of String)
    

    Visual Basic füllt die Klasse automatisch mit den Membern auf, die für die IEnumerator(Of String)-Schnittstelle erforderlich sind.

  3. Die Enumeratorklasse öffnet die Textdatei und führt die Datei-E/A aus, um die Zeilen aus der Datei zu lesen. Fügen Sie der Klasse den folgenden Code hinzu, um einen öffentlichen Konstruktor verfügbar zu machen, der einen Dateipfad als Eingabeparameter annimmt, und die Textdatei zum Lesen zu öffnen.

    Private _sr As IO.StreamReader
    
    Public Sub New(ByVal filePath As String)
        _sr = New IO.StreamReader(filePath)
    End Sub
    
  4. Die Current-Eigenschaften für die IEnumerator(Of String)- und IEnumerator-Schnittstellen geben das aktuelle Element aus der Textdatei als String zurück. Die Implementierung der Current-Eigenschaft der IEnumerator-Schnittstelle kann Private vorgenommen werden, weil Sie nur Member der IEnumerator(Of String)-Schnittstelle verfügbar machen müssen. Ersetzen Sie den Code, den Visual Basic für die Current-Eigenschaften generiert hat, durch den folgenden Code.

    Private _current As String
    
    Public ReadOnly Property Current() As String _
        Implements IEnumerator(Of String).Current
    
        Get
            If _sr Is Nothing OrElse _current Is Nothing Then
                Throw New InvalidOperationException()
            End If
    
            Return _current
        End Get
    End Property
    
    Private ReadOnly Property Current1() As Object _
        Implements IEnumerator.Current
    
        Get
            Return Me.Current
        End Get
    End Property
    
  5. Die MoveNext-Methode der IEnumerator-Schnittstelle navigiert zum nächsten Element in der Textdatei und aktualisiert den Wert, der von der Current-Eigenschaft zurückgegeben wird. Wenn keine weiteren Elemente zum Lesen vorhanden sind, gibt die MoveNext-Methode False zurück, andernfalls gibt die MoveNext-Methode True zurück. Fügen Sie der MoveNext -Methode folgenden Code hinzu.

    Public Function MoveNext() As Boolean _
        Implements System.Collections.IEnumerator.MoveNext
    
        _current = _sr.ReadLine()
        If _current Is Nothing Then Return False
        Return True
    End Function
    
  6. Die Reset-Methode der IEnumerator-Schnittstelle weist den Iterator an, auf den Anfang der Textdatei zu zeigen, und löscht den aktuellen Elementwert. Fügen Sie der Reset -Methode folgenden Code hinzu.

    Public Sub Reset() _
        Implements System.Collections.IEnumerator.Reset
    
        _sr.DiscardBufferedData()
        _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin)
        _current = Nothing
    End Sub
    
  7. Die Dispose-Methode der IEnumerator-Schnittstelle garantiert, dass alle nicht verwalteten Ressourcen freigegeben werden, bevor der Iterator zerstört wird. Das vom StreamReader-Objekt verwendete Dateihandle ist eine nicht verwaltete Ressource und muss geschlossen werden, bevor die Iteratorinstanz zerstört wird. Ersetzen Sie den Code, den Visual Basic für die Dispose-Methode generiert hat, durch den folgenden Code.

    Private disposedValue As Boolean = False
    
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' Dispose of managed resources.
            End If
            _current = Nothing
            _sr.Close()
            _sr.Dispose()
        End If
    
        Me.disposedValue = True
    End Sub
    
    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
    Protected Overrides Sub Finalize()
        Dispose(False)
    End Sub
    

Verwenden des Beispieliterators

Sie können eine aufzählbare Klasse im Code zusammen mit Steuerungsstrukturen verwenden, die ein Objekt erfordern, das IEnumerable implementiert, z. B. eine For Next-Schleife oder eine LINQ-Abfrage. Das folgende Beispiel zeigt StreamReaderEnumerable in einer LINQ-Abfrage an.

Dim adminRequests =
    From line In New StreamReaderEnumerable("..\..\log.txt")
    Where line.Contains("admin.aspx 401")

Dim results = adminRequests.ToList()

Weitere Informationen