Dela via


Genomgång: Implementera IEnumerable(Of T) i Visual Basic

Gränssnittet IEnumerable<T> implementeras av klasser som kan returnera en sekvens med värden ett objekt i taget. Fördelen med att returnera data ett objekt i taget är att du inte behöver läsa in den fullständiga uppsättningen data i minnet för att arbeta med dem. Du behöver bara använda tillräckligt med minne för att läsa in ett enda objekt från data. Klasser som implementerar IEnumerable(T) gränssnittet kan användas med For Each loopar eller LINQ-frågor.

Tänk dig till exempel ett program som måste läsa en stor textfil och returnera varje rad från filen som matchar specifika sökvillkor. Programmet använder en LINQ-fråga för att returnera rader från filen som matchar de angivna kriterierna. Om du vill köra frågor mot innehållet i filen med hjälp av en LINQ-fråga kan programmet läsa in innehållet i filen i en matris eller en samling. Att läsa in hela filen i en matris eller samling skulle dock förbruka mycket mer minne än vad som krävs. LINQ-frågan kan i stället köra frågor mot filinnehållet med hjälp av en uppräkningsbar klass och returnera endast värden som matchar sökvillkoren. Frågor som bara returnerar ett fåtal matchande värden skulle förbruka mycket mindre minne.

Du kan skapa en klass som implementerar IEnumerable<T> gränssnittet för att exponera källdata som uppräkningsbara data. Din klass som implementerar IEnumerable(T) gränssnittet kräver en annan klass som implementerar IEnumerator<T> gränssnittet för att iterera via källdata. Med de här två klasserna kan du returnera data sekventiellt som en viss typ.

I den här genomgången skapar du en klass som implementerar IEnumerable(Of String) gränssnittet och en klass som implementerar IEnumerator(Of String) gränssnittet för att läsa en textfil en rad i taget.

Kommentar

Datorn kan visa olika namn eller platser för vissa av Visual Studio-användargränssnittselementen i följande instruktioner. Den Visual Studio-utgåva som du har och de inställningar som du använder avgör dessa element. Mer information finns i Anpassa IDE.

Skapa uppräkningsbar klass

Skapa det uppräkningsbara klassprojektet

  1. I Visual Basic går du till Arkiv-menyn, pekar på Ny och klickar sedan på Projekt.

  2. I dialogrutan Nytt projekt i fönstret Projekttyper kontrollerar du att Windows är markerat. Välj Klassbibliotek i fönstret Mallar . I rutan Namn skriver du StreamReaderEnumerableoch klickar sedan på OK. Det nya projektet visas.

  3. Högerklicka på filen Class1.vb i Solution Explorer och klicka på Byt namn. Byt namn på filen till StreamReaderEnumerable.vb och tryck på RETUR. Om du byter namn på filen byter du även namn på klassen till StreamReaderEnumerable. Den här klassen implementerar IEnumerable(Of String) gränssnittet.

  4. Högerklicka på projektet StreamReaderEnumerable, peka på Lägg till och klicka sedan på Nytt objekt. Välj mallen Klass . I rutan Namn skriver du StreamReaderEnumerator.vb och klickar på OK.

Den första klassen i det här projektet är den uppräkningsbara klassen och implementerar IEnumerable(Of String) gränssnittet. Det här allmänna gränssnittet implementerar IEnumerable gränssnittet och garanterar att användare av den här klassen kan komma åt värden som skrivs som String.

Lägg till koden för att implementera IEnumerable

  1. Öppna filen StreamReaderEnumerable.vb.

  2. Skriv följande på raden efter Public Class StreamReaderEnumerableoch tryck på RETUR.

    Implements IEnumerable(Of String)
    

    Visual Basic fyller automatiskt i klassen med de medlemmar som krävs av IEnumerable(Of String) gränssnittet.

  3. Den här uppräkningsbara klassen läser rader från en textfil en rad i taget. Lägg till följande kod i klassen för att exponera en offentlig konstruktor som tar en filsökväg som indataparameter.

    Private _filePath As String
    
    Public Sub New(ByVal filePath As String)
        _filePath = filePath
    End Sub
    
  4. Implementeringen av GetEnumerator -metoden för IEnumerable(Of String) gränssnittet returnerar en ny instans av StreamReaderEnumerator klassen. Implementeringen av GetEnumerator -metoden för IEnumerable gränssnittet kan göras Private, eftersom du bara behöver exponera medlemmar i IEnumerable(Of String) gränssnittet. Ersätt koden som Visual Basic genererade för GetEnumerator metoderna med följande kod.

    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
    

Lägg till koden för att implementera IEnumerator

  1. Öppna filen StreamReaderEnumerator.vb.

  2. Skriv följande på raden efter Public Class StreamReaderEnumeratoroch tryck på RETUR.

    Implements IEnumerator(Of String)
    

    Visual Basic fyller automatiskt i klassen med de medlemmar som krävs av IEnumerator(Of String) gränssnittet.

  3. Uppräkningsklassen öppnar textfilen och utför fil-I/O för att läsa raderna från filen. Lägg till följande kod i klassen för att exponera en offentlig konstruktor som tar en filsökväg som indataparameter och öppna textfilen för läsning.

    Private _sr As IO.StreamReader
    
    Public Sub New(ByVal filePath As String)
        _sr = New IO.StreamReader(filePath)
    End Sub
    
  4. Egenskaperna Current för både gränssnitten IEnumerator(Of String) och IEnumerator returnerar det aktuella objektet från textfilen som en String. Implementeringen av Current egenskapen för IEnumerator gränssnittet kan göras Private, eftersom du bara behöver exponera medlemmar i IEnumerator(Of String) gränssnittet. Ersätt koden som Visual Basic genererade för Current egenskaperna med följande kod.

    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. Gränssnittets MoveNextIEnumerator metod navigerar till nästa objekt i textfilen och uppdaterar värdet som returneras av Current egenskapen. Om det inte finns fler objekt att läsa MoveNext returnerar Falsemetoden . Annars MoveNext returnerar Truemetoden . Lägg till följande kod i metoden MoveNext.

    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. Metoden Reset för IEnumerator gränssnittet dirigerar iteratorn till att peka på början av textfilen och rensar det aktuella objektvärdet. Lägg till följande kod i metoden Reset.

    Public Sub Reset() _
        Implements System.Collections.IEnumerator.Reset
    
        _sr.DiscardBufferedData()
        _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin)
        _current = Nothing
    End Sub
    
  7. Metoden Dispose för IEnumerator gränssnittet garanterar att alla ohanterade resurser släpps innan iteratorn förstörs. Filreferensen StreamReader som används av objektet är en ohanterad resurs och måste stängas innan iteratorinstansen förstörs. Ersätt koden som Visual Basic genererade för Dispose metoden med följande kod.

    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
    

Använda exempel-iteratorn

Du kan använda en uppräkningsbar klass i koden tillsammans med kontrollstrukturer som kräver ett objekt som implementerar IEnumerable, till exempel en For Next loop eller en LINQ-fråga. I följande exempel visas StreamReaderEnumerable i en LINQ-fråga.

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

Dim results = adminRequests.ToList()

Se även