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
I Visual Basic går du till Arkiv-menyn, pekar på Ny och klickar sedan på Projekt.
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
StreamReaderEnumerable
och klickar sedan på OK. Det nya projektet visas.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 tillStreamReaderEnumerable
. Den här klassen implementerarIEnumerable(Of String)
gränssnittet.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
Öppna filen StreamReaderEnumerable.vb.
Skriv följande på raden efter
Public Class StreamReaderEnumerable
och 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.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
Implementeringen av GetEnumerator -metoden för
IEnumerable(Of String)
gränssnittet returnerar en ny instans avStreamReaderEnumerator
klassen. Implementeringen avGetEnumerator
-metoden förIEnumerable
gränssnittet kan görasPrivate
, eftersom du bara behöver exponera medlemmar iIEnumerable(Of String)
gränssnittet. Ersätt koden som Visual Basic genererade förGetEnumerator
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
Öppna filen StreamReaderEnumerator.vb.
Skriv följande på raden efter
Public Class StreamReaderEnumerator
och 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.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
Egenskaperna
Current
för både gränssnittenIEnumerator(Of String)
ochIEnumerator
returnerar det aktuella objektet från textfilen som enString
. Implementeringen avCurrent
egenskapen förIEnumerator
gränssnittet kan görasPrivate
, eftersom du bara behöver exponera medlemmar iIEnumerator(Of String)
gränssnittet. Ersätt koden som Visual Basic genererade förCurrent
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
Gränssnittets
MoveNext
IEnumerator
metod navigerar till nästa objekt i textfilen och uppdaterar värdet som returneras avCurrent
egenskapen. Om det inte finns fler objekt att läsaMoveNext
returnerarFalse
metoden . AnnarsMoveNext
returnerarTrue
metoden . Lägg till följande kod i metodenMoveNext
.Public Function MoveNext() As Boolean _ Implements System.Collections.IEnumerator.MoveNext _current = _sr.ReadLine() If _current Is Nothing Then Return False Return True End Function
Metoden
Reset
förIEnumerator
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 metodenReset
.Public Sub Reset() _ Implements System.Collections.IEnumerator.Reset _sr.DiscardBufferedData() _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin) _current = Nothing End Sub
Metoden
Dispose
förIEnumerator
gränssnittet garanterar att alla ohanterade resurser släpps innan iteratorn förstörs. FilreferensenStreamReader
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örDispose
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()