VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > VB.net教程 >
  • 演练:在 Visual Basic 中实现 IEnumerable(Of T)

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 设置。

创建可枚举类

创建可枚举类项目

  1. 在 Visual Basic 中的“文件”菜单上,指向“新建”,然后单击“项目”

  2. “新建项目”对话框的“项目类型”窗格中,确保选中“Windows”。 在“模板”窗格中,选择“类库”。 在“名称”框中键入 StreamReaderEnumerable,然后单击“确定”。 将显示新项目。

  3. “解决方案资源管理器”中右击 Class1.vb 文件,然后选择“重命名”。 将该文件重命名为 StreamReaderEnumerable.vb,然后按 Enter。 重命名该文件后,会相应地将类重命名为 StreamReaderEnumerable。 此类将实现 IEnumerable(Of String) 接口。

  4. 右击 StreamReaderEnumerable 项目,指向“添加”,然后单击“新建项”。 选择“类”模板。 在“名称”框中键入 StreamReaderEnumerator.vb,然后单击“确定”

此项目中的第一个类是可枚举类,该类将实现 IEnumerable(Of String) 接口。 此泛型接口实现 IEnumerable 接口,并保证此类的使用方可以访问类型化为 String 的值。

添加用于实现 IEnumerable 的代码

  1. 打开 StreamReaderEnumerable.vb 文件。

  2. 在 Public Class StreamReaderEnumerable 后面的行上键入以下内容,然后按 Enter。

    Implements IEnumerable(Of String)

    Visual Basic 自动用 IEnumerable(Of String) 接口所需的成员填充该类。

  3. 此可枚举类将以一次一行的方式读取文本文件中的行。 向该类中添加以下代码,以便公开以文件路径作为输入参数的公共构造函数。

    Private _filePath As String
    
    Public Sub New(ByVal filePath As String)
        _filePath = filePath
    End Sub
  4. IEnumerable(Of String) 接口的 GetEnumerator 方法实现将返回 StreamReaderEnumerator 类的新实例。 IEnumerable 接口的 GetEnumerator 方法实现可以设置为 Private,因为只需公开 IEnumerable(Of String) 接口的成员。 用以下代码替换 Visual Basic 为 GetEnumerator 方法生成的代码。

    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

添加用于实现 IEnumerator 的代码

  1. 打开 StreamReaderEnumerator.vb 文件。

  2. 在 Public Class StreamReaderEnumerator 后面的行上键入以下内容,然后按 Enter。

    Implements IEnumerator(Of String)

    Visual Basic 自动用 IEnumerator(Of String) 接口所需的成员填充该类。

  3. 枚举器类打开文本文件,执行文件 I/O 从该文件读取行。 向该类添加以下代码,以便公开以文件路径作为输入参数的公共构造函数,并打开文本文件进行读取。

    Private _sr As IO.StreamReader
    
    Public Sub New(ByVal filePath As String)
        _sr = New IO.StreamReader(filePath)
    End Sub
  4. IEnumerator(Of String) 和 IEnumerator 接口的 Current 属性都以 String 的形式返回文本文件的当前项。 IEnumerator 接口的 Current 属性实现可以设置为 Private,因为只需公开 IEnumerator(Of String) 接口的成员。 用以下代码替换 Visual Basic 为 Current 属性生成的代码。

    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. IEnumerator 接口的 MoveNext 方法定位到文本文件的下一项并更新 Current 属性所返回的值。 如果不再有要读取的项,则 MoveNext 方法返回 False;否则,MoveNext 方法返回 True。 将以下代码添加到 MoveNext 方法中。

    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. IEnumerator 接口的 Reset 方法指示迭代器指向文本文件的开头并清除当前项的值。 将以下代码添加到 Reset 方法中。

    Public Sub Reset() _
        Implements System.Collections.IEnumerator.Reset
    
        _sr.DiscardBufferedData()
        _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin)
        _current = Nothing
    End Sub
  7. IEnumerator 接口的 Dispose 方法保证在销毁迭代器之前释放所有非托管资源。 StreamReader 对象所用的文件句柄是非托管资源,必须在迭代器实例销毁之前关闭。 用以下代码替换 Visual Basic 为 Dispose 方法生成的代码。

    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

使用示例迭代器

您可以在代码中将可枚举类用在需要实现 IEnumerable 的对象的控制结构中(如 For Next 循环或 LINQ 查询)。 下面的示例演示 LINQ 查询中的 StreamReaderEnumerable。

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

Dim results = adminRequests.ToList()

 


原文链接:https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/dd145423(v=vs.100)

相关教程