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. 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. The application uses a LINQ query to return lines from the file that match the specified criteria. 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. 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.
You can create a class that implements the IEnumerable<T> interface to expose source data as enumerable data. 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.
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.
Your computer might show different names or locations for some of the Visual Studio user interface elements in the following instructions. The Visual Studio edition that you have and the settings that you use determine these elements. For more information, see Personalizing the Visual Studio IDE.
In Visual Basic, on the File menu, point to New and then click Project.
In the New Project dialog box, in the Project Types pane, make sure that Windows is selected. Select Class Library in the Templates pane. In the Name box, type StreamReaderEnumerable, and then click OK. The new project is displayed.
In Solution Explorer, right-click the Class1.vb file and click Rename. Rename the file to StreamReaderEnumerable.vb and press ENTER. Renaming the file will also rename the class to StreamReaderEnumerable. This class will implement the IEnumerable(Of String) interface.
Right-click the StreamReaderEnumerable project, point to Add, and then click New Item. Select the Class template. In the Name box, type StreamReaderEnumerator.vb and click OK.
The first class in this project is the enumerable class and will implement the IEnumerable(Of String) interface. This generic interface implements the IEnumerable interface and guarantees that consumers of this class can access values typed as String.
To add the code to implement IEnumerable
Open the StreamReaderEnumerable.vb file.
On the line after Public Class StreamReaderEnumerable, type the following and press ENTER.
Your implementation of the GetEnumerator method of the IEnumerable(Of String) interface will return a new instance of the StreamReaderEnumerator class. 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. Replace the code that Visual Basic generated for the GetEnumerator methods with the following code.
' Return a new object that matches 'this' object's permissions.PublicOverridesFunction Copy() As IPermission
Visual Basic automatically populates the class with the members that are required by the IEnumerator(Of String) interface.
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
PublicSubNew(ByVal filePath AsString)
_sr = New IO.StreamReader(filePath)
The Current properties for both the IEnumerator(Of String) and IEnumerator interfaces return the current item from the text file as a 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. Replace the code that Visual Basic generated for the Current properties with the following code.
The 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. If there are no more items to read, the MoveNext method returns False; otherwise the MoveNext method returns True. Add the following code to the MoveNext method.
The Dispose method of the IEnumerator interface guarantees that all unmanaged resources are released before the iterator is destroyed. The file handle that is used by the StreamReader object is an unmanaged resource and must be closed before the iterator instance is destroyed. Replace the code that Visual Basic generated for the Dispose method with the following code.
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. The following example shows the StreamReaderEnumerable in a LINQ query.