IEnumerable<T> 接口由可以以一次一项的方式返回值序列的类实现。一次返回一项数据的好处在于,无需将整个数据集加载到内存中进行处理。而只需为加载的单个数据项提供足够的内存。实现 IEnumerable(T) 接口的类可用在 For Each 循环或 LINQ 查询中。
例如,假设应用程序必须读取一个大型文本文件,并从该文件中返回符合特定搜索条件的每一行。应用程序使用 LINQ 查询从该文件中返回符合指定条件的行。若要使用 LINQ 查询来查询文件的内容,应用程序可以将文件的内容加载到一个数组或集合中。但是,将整个文件加载到数组或集合会占用太多不必要的内存。LINQ 查询可以改为使用可枚举类来查询文件内容,仅返回符合搜索条件的值。仅返回一些匹配值的查询所占用的内存将会少得多。
可以创建实现 IEnumerable<T> 接口的类将源数据公开为可枚举数据。实现 IEnumerable(T) 接口的类需要另一个实现 IEnumerator<T> 接口的类,以便循环访问源数据。使用这两个类,可以按顺序以特定类型的形式返回数据项。
在本演练中,将创建一个实现 IEnumerable(Of String) 接口的类以及一个实现 IEnumerator(Of String) 接口的类,以便一次从文本文件中读取一行。
对于在以下说明中使用的某些 Visual Studio 用户界面元素,您的计算机可能会显示不同的名称或位置。这些元素取决于您所使用的 Visual Studio 版本和您所使用的设置。有关更多信息,请参见 Visual Studio 设置。 |
创建可枚举类
创建可枚举类项目 |
在 Visual Basic 中的“文件”菜单上,指向“新建”,然后单击“项目”。
在“新建项目”对话框的“项目类型”窗格中,确保选中“Windows”。在“模板”窗格中,选择“类库”。在“名称”框中键入 StreamReaderEnumerable,然后单击“确定”。将显示新项目。
在“解决方案资源管理器”中右击 Class1.vb 文件,然后选择“重命名”。将该文件重命名为 StreamReaderEnumerable.vb,然后按 Enter。重命名该文件后,会相应地将类重命名为 StreamReaderEnumerable。此类将实现 IEnumerable(Of String) 接口。
右击 StreamReaderEnumerable 项目,指向“添加”,然后单击“新建项”。选择“类”模板。在“名称”框中键入 StreamReaderEnumerator.vb,然后单击“确定”。
|
此项目中的第一个类是可枚举类,该类将实现 IEnumerable(Of String) 接口。此泛型接口实现 IEnumerable 接口,并保证此类的使用方可以访问类型化为 String 的值。
添加用于实现 IEnumerable 的代码 |
打开 StreamReaderEnumerable.vb 文件。
在 Public Class StreamReaderEnumerable 后面的行上键入以下内容,然后按 Enter。
Visual Basic 自动用 IEnumerable(Of String) 接口所需的成员填充该类。
此可枚举类将以一次一行的方式读取文本文件中的行。向该类中添加以下代码,以便公开以文件路径作为输入参数的公共构造函数。
IEnumerable(Of String) 接口的 GetEnumerator 方法实现将返回 StreamReaderEnumerator 类的新实例。IEnumerable 接口的 GetEnumerator 方法实现可以设置为 Private,因为只需公开 IEnumerable(Of String) 接口的成员。用以下代码替换 Visual Basic 为 GetEnumerator 方法生成的代码。
|
添加用于实现 IEnumerator 的代码 |
打开 StreamReaderEnumerator.vb 文件。
在 Public Class StreamReaderEnumerator 后面的行上键入以下内容,然后按 Enter。
Visual Basic 自动用 IEnumerator(Of String) 接口所需的成员填充该类。
枚举器类打开文本文件,执行文件 I/O 从该文件读取行。向该类添加以下代码,以便公开以文件路径作为输入参数的公共构造函数,并打开文本文件进行读取。
IEnumerator(Of String) 和 IEnumerator 接口的 Current 属性都以 String 的形式返回文本文件的当前项。IEnumerator 接口的 Current 属性实现可以设置为 Private,因为只需公开 IEnumerator(Of String) 接口的成员。用以下代码替换 Visual Basic 为 Current 属性生成的代码。
IEnumerator 接口的 MoveNext 方法定位到文本文件的下一项并更新 Current 属性所返回的值。如果不再有要读取的项,则 MoveNext 方法返回 False;否则,MoveNext 方法返回 True。将以下代码添加到 MoveNext 方法中。
IEnumerator 接口的 Reset 方法指示迭代器指向文本文件的开头并清除当前项的值。将以下代码添加到 Reset 方法中。
IEnumerator 接口的 Dispose 方法保证在销毁迭代器之前释放所有非托管资源。StreamReader 对象所用的文件句柄是非托管资源,必须在迭代器实例销毁之前关闭。用以下代码替换 Visual Basic 为 Dispose 方法生成的代码。
|
使用示例迭代器
您可以在代码中将可枚举类用在需要实现 IEnumerable 的对象的控制结构中(如 For Next 循环或 LINQ 查询)。下面的示例演示 LINQ 查询中的 StreamReaderEnumerable。
Dim adminRequests =
From line In New StreamReaderEnumerable("..\..\log.txt")
Where line.Contains("admin.aspx 401")
Dim results = adminRequests.ToList()
请参见
参考
For Each...Next 语句 (Visual Basic)
概念
Visual Basic 中的 LINQ 简介
循环结构 (Visual Basic)
其他资源
控制流 (Visual Basic)