逐步解說:在 Visual Basic 中實作 IEnumerable(Of T)Walkthrough: Implementing IEnumerable(Of T) in Visual Basic

IEnumerable<T>介面是由可傳回一次一個專案的一系列值的類別所執行。The IEnumerable<T> interface is implemented by classes that can return a sequence of values one item at a time. 一次只傳回一個專案的優點是,您不需要將一組完整的資料載入記憶體中,就能使用它。The advantage of returning data one item at a time is that you do not have to load the complete set of data into memory to work with it. 您只需要使用足夠的記憶體從資料載入單一專案。You only have to use sufficient memory to load a single item from the data. 執行介面的類別 IEnumerable(T) 可以搭配 For Each 迴圈或 LINQ 查詢使用。Classes that implement the IEnumerable(T) interface can be used with For Each loops or LINQ queries.

例如,假設應用程式必須讀取大型文字檔,並從符合特定搜尋準則的檔案傳回每一行。For example, consider an application that must read a large text file and return each line from the file that matches particular search criteria. 應用程式會使用 LINQ 查詢,從檔案傳回符合指定準則的行。The application uses a LINQ query to return lines from the file that match the specified criteria. 若要使用 LINQ 查詢來查詢檔案的內容,應用程式可以將檔案的內容載入陣列或集合中。To query the contents of the file by using a LINQ query, the application could load the contents of the file into an array or a collection. 不過,將整個檔案載入至陣列或集合中的記憶體,會比所需的記憶體多出許多。However, loading the whole file into an array or collection would consume far more memory than is required. LINQ 查詢可以改為使用可列舉類別來查詢檔案內容,只傳回符合搜尋準則的值。The LINQ query could instead query the file contents by using an enumerable class, returning only values that match the search criteria. 只傳回幾個相符值的查詢會耗用較少的記憶體。Queries that return only a few matching values would consume far less memory.

您可以建立一個類別來執行 IEnumerable<T> 介面,以將來源資料公開為可列舉的資料。You can create a class that implements the IEnumerable<T> interface to expose source data as enumerable data. 您執行介面的類別 IEnumerable(T) 需要另一個類別來 IEnumerator<T> 執行介面,以逐一查看來源資料。Your class that implements the IEnumerable(T) interface will require another class that implements the IEnumerator<T> interface to iterate through the source data. 這兩個類別可讓您以特定類型的順序傳回資料的專案。These two classes enable you to return items of data sequentially as a specific type.

在這個逐步解說中,您將建立一個類別,它會執行 IEnumerable(Of String) 介面和一個類別,該類別會 IEnumerator(Of String) 執行介面,一次一行讀取文字檔。In this walkthrough, you will create a class that implements the IEnumerable(Of String) interface and a class that implements the IEnumerator(Of String) interface to read a text file one line at a time.

注意

在下列指示的某些 Visual Studio 使用者介面項目中,您的電腦可能會顯示不同的名稱或位置:Your computer might show different names or locations for some of the Visual Studio user interface elements in the following instructions. 您所擁有的 Visual Studio 版本以及使用的設定會決定這些項目。The Visual Studio edition that you have and the settings that you use determine these elements. 如需詳細資訊,請參閱將 Visual Studio IDE 個人化For more information, see Personalizing the IDE.

建立可列舉類別Creating the Enumerable Class

建立可列舉類別專案Create the enumerable class project

  1. 在 Visual Basic 的 [檔案 ] 功能表上,指向 [ 新增 ],然後按一下 [ 專案]。In Visual Basic, on the File menu, point to New and then click Project.

  2. 在 [新增專案] 對話方塊的 [專案類型] 窗格中,確認已選取 [Windows]。In the New Project dialog box, in the Project Types pane, make sure that Windows is selected. 在 [範本] 窗格中,選取 [類別庫]。Select Class Library in the Templates pane. 在 [名稱] 方塊中,輸入 StreamReaderEnumerable 並按一下 [確定]。In the Name box, type StreamReaderEnumerable, and then click OK. 新的專案隨即顯示。The new project is displayed.

  3. 方案總管 中,以滑鼠右鍵按一下 Class1 檔案,然後按一下 [ 重新命名]。In Solution Explorer, right-click the Class1.vb file and click Rename. 將檔案重新命名為 StreamReaderEnumerable.vb,然後按 ENTER。Rename the file to StreamReaderEnumerable.vb and press ENTER. 重新命名檔案時,也會將類別重新命名為 StreamReaderEnumerableRenaming the file will also rename the class to StreamReaderEnumerable. 此類別會實作 IEnumerable(Of String) 介面。This class will implement the IEnumerable(Of String) interface.

  4. 以滑鼠右鍵按一下 StreamReaderEnumerable 專案,指向 [ 加入],然後按一下 [ 新增專案]。Right-click the StreamReaderEnumerable project, point to Add, and then click New Item. 選取 [ 類別 ] 範本。Select the Class template. 在 [名稱] 方塊中輸入 StreamReaderEnumerator.vb,然後按一下 [確定]。In the Name box, type StreamReaderEnumerator.vb and click OK.

此專案中的第一個類別是可列舉的類別,而且將會執行 IEnumerable(Of String) 介面。The first class in this project is the enumerable class and will implement the IEnumerable(Of String) interface. 這個泛型介面會實 IEnumerable 作為介面,並保證這個類別的取用者可以存取輸入的值 StringThis generic interface implements the IEnumerable interface and guarantees that consumers of this class can access values typed as String.

新增程式碼以執行 IEnumerableAdd the code to implement IEnumerable

  1. 開啟 StreamReaderEnumerable .vb 檔案。Open the StreamReaderEnumerable.vb file.

  2. 在 [後行] Public Class StreamReaderEnumerable 中,輸入下列程式碼,然後按 enter 鍵。On the line after Public Class StreamReaderEnumerable, type the following and press ENTER.

    Implements IEnumerable(Of String)
    

    Visual Basic 會自動將介面所需的成員填入類別 IEnumerable(Of String)Visual Basic automatically populates the class with the members that are required by the IEnumerable(Of String) interface.

  3. 這個可列舉類別會一次從文字檔讀取一行。This enumerable class will read lines from a text file one line at a time. 將下列程式碼加入至類別,以公開接受檔案路徑做為輸入參數的公用函式。Add the following code to the class to expose a public constructor that takes a file path as an input parameter.

    Private _filePath As String
    
    Public Sub New(ByVal filePath As String)
        _filePath = filePath
    End Sub
    
  4. 您對介面的 GetEnumerator 方法的執行 IEnumerable(Of String) 將會傳回類別的新實例 StreamReaderEnumeratorYour implementation of the GetEnumerator method of the IEnumerable(Of String) interface will return a new instance of the StreamReaderEnumerator class. GetEnumerator IEnumerable 您可以執行介面的方法 Private ,因為您必須只公開介面的成員 IEnumerable(Of String)The implementation of the GetEnumerator method of the IEnumerable interface can be made Private, because you have to expose only members of the IEnumerable(Of String) interface. 以下列程式碼取代 Visual Basic 為方法產生的程式碼 GetEnumeratorReplace the code that Visual Basic generated for the GetEnumerator methods with the following 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
    

新增程式碼以執行 IEnumeratorAdd the code to implement IEnumerator

  1. 開啟 StreamReaderEnumerator .vb 檔案。Open the StreamReaderEnumerator.vb file.

  2. 在 [後行] Public Class StreamReaderEnumerator 中,輸入下列程式碼,然後按 enter 鍵。On the line after Public Class StreamReaderEnumerator, type the following and press ENTER.

    Implements IEnumerator(Of String)
    

    Visual Basic 會自動將介面所需的成員填入類別 IEnumerator(Of String)Visual Basic automatically populates the class with the members that are required by the IEnumerator(Of String) interface.

  3. 列舉值類別會開啟文字檔,並執行檔案 i/o 以讀取檔案中的行。The enumerator class opens the text file and performs the file I/O to read the lines from the file. 將下列程式碼加入至類別,以公開公用的函式,該函式會使用檔案路徑做為輸入參數,並開啟文字檔進行讀取。Add the following code to the class to expose a public constructor that takes a file path as an input parameter and open the text file for reading.

    Private _sr As IO.StreamReader
    
    Public Sub New(ByVal filePath As String)
        _sr = New IO.StreamReader(filePath)
    End Sub
    
  4. Current和介面的屬性會 IEnumerator(Of String) IEnumerator 從文字檔傳回目前的專案做為 StringThe Current properties for both the IEnumerator(Of String) and IEnumerator interfaces return the current item from the text file as a String. Current IEnumerator Private 因為您必須只公開介面的成員,所以可以執行介面的屬性 IEnumerator(Of String)The implementation of the Current property of the IEnumerator interface can be made Private, because you have to expose only members of the IEnumerator(Of String) interface. 以下列程式碼取代 Visual Basic 為屬性產生的程式碼 CurrentReplace the code that Visual Basic generated for the Current properties with the following 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. MoveNext介面的方法會 IEnumerator 流覽至文字檔中的下一個專案,並更新屬性所傳回的值 CurrentThe MoveNext method of the IEnumerator interface navigates to the next item in the text file and updates the value that is returned by the Current property. 如果沒有其他要讀取的專案,方法會傳回 MoveNext False ; 否則, MoveNext 方法 True 會傳回。If there are no more items to read, the MoveNext method returns False; otherwise the MoveNext method returns True. 將下列程式碼新增至 MoveNext 方法。Add the following code to the MoveNext method.

    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. Reset介面的方法會 IEnumerator 指示反覆運算器指向文字檔的開頭,並清除目前的專案值。The Reset method of the IEnumerator interface directs the iterator to point to the start of the text file and clears the current item value. 將下列程式碼新增至 Reset 方法。Add the following code to the Reset method.

    Public Sub Reset() _
        Implements System.Collections.IEnumerator.Reset
    
        _sr.DiscardBufferedData()
        _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin)
        _current = Nothing
    End Sub
    
  7. Dispose介面的方法可 IEnumerator 保證在反覆運算器終結之前釋放所有非受控資源。The Dispose method of the IEnumerator interface guarantees that all unmanaged resources are released before the iterator is destroyed. 物件所使用的檔案控制代碼 StreamReader 是未受管理的資源,而且必須在終結 iterator 實例之前關閉。The file handle that is used by the StreamReader object is an unmanaged resource and must be closed before the iterator instance is destroyed. 以下列程式碼取代 Visual Basic 為方法產生的程式碼 DisposeReplace the code that Visual Basic generated for the Dispose method with the following 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
    

使用範例反覆運算器Using the Sample Iterator

您可以使用程式碼中的可列舉類別,以及需要執行物件( IEnumerable 例如 For Next 迴圈或 LINQ 查詢)的控制結構。You can use an enumerable class in your code together with control structures that require an object that implements IEnumerable, such as a For Next loop or a LINQ query. 下列範例顯示 StreamReaderEnumerable LINQ 查詢中的。The following example shows the StreamReaderEnumerable in a LINQ query.

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

Dim results = adminRequests.ToList()

另請參閱See also