Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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 IEnumerable(Of String), oraz klasę, która implementuje interfejs IEnumerator(Of String), aby odczytywać plik tekstowy po jednej linii naraz.
Uwaga / Notatka
Na komputerze mogą być wyświetlane różne nazwy lub lokalizacje niektórych elementów interfejsu użytkownika programu Visual Studio w poniższych instrukcjach. Wersja programu Visual Studio i ustawienia, których używasz, określają te elementy. 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 Eksploratorze rozwiązań kliknij prawym przyciskiem myszy plik Class1.vb i kliknij polecenie Zmień nazwę. Zmień nazwę pliku na
StreamReaderEnumerable.vbi naciśnij 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.vbi kliknij przycisk OK.
Pierwszą klasą projektu będzie klasa wyliczalna, która zaimplementuje interfejs IEnumerable(Of String). 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 StreamReaderEnumerablewpisz następujący tekst i naciśnij ENTER.Implements IEnumerable(Of String)Visual Basic automatycznie wypełnia klasę członkami wymaganymi przez interfejs
IEnumerable(Of String).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 SubImplementacja GetEnumerator metody interfejsu
IEnumerable(Of String)zwróci nowe wystąpienieStreamReaderEnumeratorklasy. ImplementacjęGetEnumeratormetody interfejsuIEnumerablemożna wykonaćPrivate, ponieważ trzeba uwidocznić tylko członków interfejsuIEnumerable(Of String). Zastąp kod wygenerowany w języku Visual Basic dlaGetEnumeratormetod 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 StreamReaderEnumeratorwpisz następujący tekst i naciśnij ENTER.Implements IEnumerator(Of String)Visual Basic automatycznie wypełnia klasę członkami wymaganymi przez interfejs
IEnumerator(Of String).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 SubWłaściwości
Currentdla interfejsówIEnumerator(Of String)iIEnumeratorzwracają bieżący element z pliku tekstowego jakoString. Implementację właściwościCurrentinterfejsuIEnumeratormożna wykonaćPrivate, ponieważ trzeba ujawnić tylko członków interfejsuIEnumerator(Of String). Zastąp kod wygenerowany przez program Visual Basic dlaCurrentwł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 PropertyMetoda
MoveNextz interfejsuIEnumeratorprzemieszcza się do następnego elementu w pliku tekstowym i aktualizuje wartość, którą zwraca właściwośćCurrent. Jeśli nie ma więcej elementów do odczytania, metodaMoveNextzwracaFalse; w przeciwnym razie metodaMoveNextzwracaTrue. 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 FunctionMetoda
ResetinterfejsuIEnumeratorkieruje 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 SubMetoda
DisposeinterfejsuIEnumeratorgwarantuje, że wszystkie niezarządzane zasoby zostaną zwolnione przed zniszczeniem iteratora. Uchwyt pliku używany przezStreamReaderobiekt jest zasobem niezarządzanym i musi zostać zamknięty przed zniszczeniem instancji iteratora. Zastąp kod wygenerowany przez program Visual Basic dlaDisposemetody 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ącego IEnumerable, takiego jak pętla For Next lub zapytanie LINQ. W poniższym przykładzie pokazano StreamReaderEnumerable w zapytaniu LINQ.
Dim adminRequests =
From line In New StreamReaderEnumerable("..\..\log.txt")
Where line.Contains("admin.aspx 401")
Dim results = adminRequests.ToList()