Export (0) Print
Expand All

IEnumerable(Of T).GetEnumerator Method

Returns an enumerator that iterates through the collection.

Namespace:  System.Collections.Generic
Assembly:  mscorlib (in mscorlib.dll)

'Declaration
Function GetEnumerator As IEnumerator(Of T)

Return Value

Type: System.Collections.Generic.IEnumerator(Of T)
An enumerator that can be used to iterate through the collection.

The returned IEnumerator(Of T) provides the ability to iterate through the collection by exposing a Current property .You can use enumerators to read the data in a collection, but not to modify the collection.

Initially, the enumerator is positioned before the first element in the collection. At this position, Current is undefined. Therefore, you must call the MoveNext method to advance the enumerator to the first element of the collection before reading the value of Current.

Current returns the same object until MoveNext is called again as MoveNext sets Current to the next element.

If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false. When the enumerator is at this position, subsequent calls to MoveNext also return false. If the last call to MoveNext returned false, Current is undefined. You cannot set Current to the first element of the collection again; you must create a new enumerator instance instead.

An enumerator does not have exclusive access to the collection so an enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is invalidated and you may get unexpected results when a. Also, enumerating a collection is not a thread-safe procedure. To guarantee thread-safety, you should lock the collection during enumerator or implement synchronization on the collection.

Default implementations of collections in the System.Collections.Generic namespace aren't synchronized.

The following example demonstrates how to implement the IEnumerable(Of T) interface and uses that implementation to create a LINQ query. When you implement IEnumerable(Of T), you must also implement IEnumerator(Of T) or, for C# only, you can use the yield (C# Reference) keyword. Implementing IEnumerator(Of T) also requires IDisposable to be implemented, which you will see in this example.

Option Strict On 
Public Class App
    ' Excercise the Iterator and show that it's more 
    ' performant. 
    Public Shared Sub Main()
        TestStreamReaderEnumerable()
        TestReadingFile()
    End Sub 

    Shared Sub TestStreamReaderEnumerable()
        ' Check the memory before the iterator is used. 
        Dim memoryBefore = GC.GetTotalMemory(True)

        ' Open a file with the StreamReaderEnumerable and check for a string. 
        Dim stringsFound =
            From line In New StreamReaderEnumerable("c:\temp\tempFile.txt")
            Where line.Contains("string to search for")

        Console.WriteLine("Found:" & stringsFound.Count())

        ' Check the memory after the iterator and output it to the console. 
        Dim memoryAfter = GC.GetTotalMemory(False)
        Console.WriteLine("Memory Used With Iterator = " & vbTab & Format((memoryAfter - memoryBefore) / 1000, "n") & "kb")
    End Sub 

    Shared Sub TestReadingFile()
        Dim memoryBefore = GC.GetTotalMemory(True)

        ' Open a file with a regular file reader. 
        Dim sr = My.Computer.FileSystem.OpenTextFileReader("c:\temp\tempFile.txt")

        ' Add the file contents to a generic list of strings. 
        Dim fileContents As New List(Of String)
        While Not sr.EndOfStream
            fileContents.Add(sr.ReadLine())
        End While 

        ' Check for the string. 
        Dim stringsFound =
            From line In fileContents
            Where line.Contains("string to search for")

        sr.Close()
        Console.WriteLine("Found: " & stringsFound.Count())
        ' Check the memory after when the iterator is not used, and output it to the console. 
        Dim memoryAfter = GC.GetTotalMemory(False)
        Console.WriteLine("Memory Used Without Iterator = " &
                          vbTab & Format((memoryAfter - memoryBefore) / 1000, "n") & "kb")

    End Sub 
End Class 

' A custom class that implements IEnumerable(T). When you implement IEnumerable(T),  
' you must also implement IEnumerable and IEnumerator(T). 
Public Class StreamReaderEnumerable
    Implements IEnumerable(Of String)

    Private _filePath As String 

    Public Sub New(ByVal filePath As String)
        _filePath = filePath
    End Sub 


    ' Must implement GetEnumerator, which returns a new StreamReaderEnumerator. 
    Public Function GetEnumerator() As IEnumerator(Of String) _
        Implements IEnumerable(Of String).GetEnumerator

        Return New StreamReaderEnumerator(_filePath)
    End Function 

    ' Must also implement IEnumerable.GetEnumerator, but implement as a private method. 
    Private Function GetEnumerator1() As IEnumerator _
        Implements IEnumerable.GetEnumerator

        Return Me.GetEnumerator()
    End Function 

End Class 

' When you implement IEnumerable(T), you must also implement IEnumerator(T),  
' which will walk through the contents of the file one line at a time. 
' Implementing IEnumerator(T) requires that you implement IEnumerator and IDisposable. 
Public Class StreamReaderEnumerator
    Implements IEnumerator(Of String)

    Private _sr As IO.StreamReader

    Public Sub New(ByVal filePath As String)
        _sr = New IO.StreamReader(filePath)
    End Sub 

    Private _current As String 

    ' Implement the IEnumerator(T).Current publicly, but implement  
    ' IEnumerator.Current, which is also required, privately. 
    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 

    ' Implement MoveNext and Reset, which are required by IEnumerator. 
    Public Function MoveNext() As Boolean _
        Implements System.Collections.IEnumerator.MoveNext

        _current = _sr.ReadLine()
        If _current Is Nothing Then Return False 
        Return True 
    End Function 

    Public Sub Reset() _
        Implements System.Collections.IEnumerator.Reset

        _sr.DiscardBufferedData()
        _sr.BaseStream.Seek(0, IO.SeekOrigin.Begin)
        _current = Nothing 
    End Sub 

    ' Implement IDisposable, which is also implemented by IEnumerator(T). 
    Private disposedValue As Boolean = False 

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub 
    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 

    Protected Overrides Sub Finalize()
        Dispose(False)
    End Sub 

End Class 
' This example displays output similar to the following: 
' Found:2 
' Memory Used With Iterator =     32.77kb 
' Found: 2 
' Memory Used Without Iterator =  37.94kb

For another C# example that demonstrates how to implement the IEnumerable(Of T) interface, see the Generics Sample. This sample uses of the yield keyword instead of implementing IEnumerator(Of T).

.NET Framework

Supported in: 4.5, 4, 3.5, 3.0, 2.0

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Portable Class Library

Supported in: Portable Class Library

.NET for Windows Store apps

Supported in: Windows 8

.NET for Windows Phone apps

Supported in: Windows Phone 8.1, Windows Phone Silverlight 8.1, Windows Phone Silverlight 8

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Show:
© 2014 Microsoft