Wskazówki: wdrażanie IEnumerable(Of T) w Visual Basic
Interfejs IEnumerable<T> jest implementowany przez klasy, które mogą zwracać sekwencję wartości jeden element naraz. Zaletą zwracania danych w danym momencie jest to, że nie trzeba ładować pełnego zestawu danych do pamięci, aby z nim pracować. Wystarczy użyć wystarczającej ilości pamięci, aby załadować pojedynczy element z danych. Klasy implementujące IEnumerable(T)
interfejs mogą być używane z pętlami For Each
lub zapytaniami LINQ.
Rozważmy na przykład aplikację, która musi odczytać duży plik tekstowy i zwrócić każdy wiersz z pliku, który spełnia określone kryteria wyszukiwania. Aplikacja używa zapytania LINQ do zwracania wierszy z pliku, które spełniają określone kryteria. Aby zbadać zawartość pliku przy użyciu zapytania LINQ, aplikacja może załadować zawartość pliku do tablicy lub kolekcji. Jednak załadowanie całego pliku do tablicy lub kolekcji zużywałoby znacznie więcej pamięci niż jest to wymagane. Zapytanie LINQ może zamiast tego wykonywać zapytania dotyczące zawartości pliku przy użyciu klasy wyliczalnej, zwracając tylko wartości spełniające kryteria wyszukiwania. Zapytania zwracające tylko kilka pasujących wartości zużywają znacznie mniej pamięci.
Możesz utworzyć klasę, która implementuje IEnumerable<T> interfejs w celu uwidaczniania danych źródłowych jako danych wyliczalnych. Klasa, która implementuje IEnumerable(T)
interfejs, będzie wymagać innej klasy, która implementuje IEnumerator<T> interfejs do iterowania danych źródłowych. Te dwie klasy umożliwiają sekwencyjne zwracanie elementów danych jako określonego typu.
W tym przewodniku utworzysz klasę, która implementuje interfejs i klasę, która implementuje IEnumerable(Of String)
IEnumerator(Of String)
interfejs w celu odczytania pliku tekstowego po jednym wierszu naraz.
Uwaga
Na komputerze w poniższych instrukcjach mogą być wyświetlane inne nazwy i lokalizacje niektórych elementów interfejsu użytkownika programu Visual Studio. Te elementy są określane przez numer wersji Visual Studio oraz twoje ustawienia. Aby uzyskać więcej informacji, zobacz Personalizowanie środowiska IDE.
Tworzenie klasy Enumerable
Tworzenie projektu klasy wyliczalnej
W języku Visual Basic w menu Plik wskaż polecenie Nowy , a następnie kliknij pozycję Projekt.
W oknie dialogowym Nowy projekt w okienku Typy projektów upewnij się, że wybrano pozycję Windows. Wybierz pozycję Biblioteka klas w okienku Szablony . W polu Nazwa wpisz
StreamReaderEnumerable
, a następnie kliknij przycisk OK. Zostanie wyświetlony nowy projekt.W Eksplorator rozwiązań kliknij prawym przyciskiem myszy plik Class1.vb i kliknij polecenie Zmień nazwę. Zmień nazwę pliku na
StreamReaderEnumerable.vb
i naciśnij klawisz ENTER. Zmiana nazwy pliku spowoduje również zmianę nazwy klasy naStreamReaderEnumerable
. Ta klasa zaimplementujeIEnumerable(Of String)
interfejs.Kliknij prawym przyciskiem myszy projekt StreamReaderEnumerable, wskaż polecenie Dodaj, a następnie kliknij pozycję Nowy element. Wybierz szablon Klasa. W polu Nazwa wpisz
StreamReaderEnumerator.vb
i kliknij przycisk OK.
Pierwszą klasą w tym projekcie jest klasa wyliczalna i zaimplementuje IEnumerable(Of String)
interfejs. Ten interfejs ogólny implementuje IEnumerable interfejs i gwarantuje, że użytkownicy tej klasy mogą uzyskać dostęp do wartości wpisanych jako String
.
Dodawanie kodu w celu zaimplementowania funkcji IEnumerable
Otwórz plik StreamReaderEnumerable.vb.
W wierszu po
Public Class StreamReaderEnumerable
wpisz następujący tekst i naciśnij klawisz ENTER.Implements IEnumerable(Of String)
Program Visual Basic automatycznie wypełnia klasę elementami członkowskimi wymaganymi przez
IEnumerable(Of String)
interfejs.Ta klasa wyliczalna odczytuje wiersze z pliku tekstowego po jednym wierszu naraz. Dodaj następujący kod do klasy, aby uwidocznić publiczny konstruktor, który przyjmuje ścieżkę pliku jako parametr wejściowy.
Private _filePath As String Public Sub New(ByVal filePath As String) _filePath = filePath End Sub
Implementacja GetEnumerator metody interfejsu
IEnumerable(Of String)
zwróci nowe wystąpienieStreamReaderEnumerator
klasy. ImplementacjęGetEnumerator
metody interfejsuIEnumerable
można wykonaćPrivate
, ponieważ trzeba uwidocznić tylko elementy członkowskie interfejsuIEnumerable(Of String)
. Zastąp kod wygenerowany w języku Visual Basic dlaGetEnumerator
metod następującym kodem.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
Dodawanie kodu w celu zaimplementowania modułu IEnumerator
Otwórz plik StreamReaderEnumerator.vb.
W wierszu po
Public Class StreamReaderEnumerator
wpisz następujący tekst i naciśnij klawisz ENTER.Implements IEnumerator(Of String)
Program Visual Basic automatycznie wypełnia klasę elementami członkowskimi wymaganymi przez
IEnumerator(Of String)
interfejs.Klasa modułu wyliczającego otwiera plik tekstowy i wykonuje operacje we/wy pliku w celu odczytania wierszy z pliku. Dodaj następujący kod do klasy, aby uwidocznić publiczny konstruktor, który przyjmuje ścieżkę pliku jako parametr wejściowy, a następnie otwórz plik tekstowy do odczytu.
Private _sr As IO.StreamReader Public Sub New(ByVal filePath As String) _sr = New IO.StreamReader(filePath) End Sub
Właściwości
Current
dla interfejsówIEnumerator(Of String)
iIEnumerator
zwracają bieżący element z pliku tekstowego jakoString
. ImplementacjęCurrent
właściwościIEnumerator
interfejsu można wykonaćPrivate
, ponieważ trzeba uwidocznić tylko elementy członkowskie interfejsuIEnumerator(Of String)
. Zastąp kod wygenerowany przez program Visual Basic dlaCurrent
właściwości następującym kodem.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
Metoda
MoveNext
interfejsuIEnumerator
przechodzi do następnego elementu w pliku tekstowym i aktualizuje wartość zwracaną przezCurrent
właściwość . Jeśli nie ma więcej elementów do odczytaniaMoveNext
, metoda zwracaFalse
wartość ; w przeciwnym razieMoveNext
metoda zwracaTrue
wartość . Dodaj następujący kod do metodyMoveNext
:Public Function MoveNext() As Boolean _ Implements System.Collections.IEnumerator.MoveNext _current = _sr.ReadLine() If _current Is Nothing Then Return False Return True End Function
Metoda
Reset
interfejsuIEnumerator
kieruje iterator, aby wskazywał początek pliku tekstowego i czyści bieżącą wartość elementu. Dodaj następujący kod do metodyReset
:Public Sub Reset() _ Implements System.Collections.IEnumerator.Reset _sr.DiscardBufferedData() _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin) _current = Nothing End Sub
Metoda
Dispose
interfejsuIEnumerator
gwarantuje, że wszystkie niezarządzane zasoby zostaną zwolnione przed zniszczeniem iteratora. Uchwyt pliku używany przezStreamReader
obiekt jest zasobem niezarządzanym i musi zostać zamknięty przed zniszczeniem wystąpienia iteratora. Zastąp kod wygenerowany przez program Visual Basic dlaDispose
metody następującym kodem.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
Korzystanie z iteratora przykładowego
Można użyć klasy wyliczalnej w kodzie wraz ze strukturami sterującymi, które wymagają obiektu implementujące IEnumerable
obiekt , taki jak pętla For Next
lub zapytanie LINQ. W poniższym przykładzie pokazano StreamReaderEnumerable
element w zapytaniu LINQ.
Dim adminRequests =
From line In New StreamReaderEnumerable("..\..\log.txt")
Where line.Contains("admin.aspx 401")
Dim results = adminRequests.ToList()