IEnumerable<T>.GetEnumerator IEnumerable<T>.GetEnumerator IEnumerable<T>.GetEnumerator IEnumerable<T>.GetEnumerator Method

定義

コレクションを反復処理する列挙子を返します。Returns an enumerator that iterates through the collection.

public:
 System::Collections::Generic::IEnumerator<T> ^ GetEnumerator();
public System.Collections.Generic.IEnumerator<out T> GetEnumerator ();
abstract member GetEnumerator : unit -> System.Collections.Generic.IEnumerator<'T>
Public Function GetEnumerator () As IEnumerator(Of Out T)

戻り値

コレクションの反復処理に使用できる列挙子。An enumerator that can be used to iterate through the collection.

次の例は、実装する方法を示します、IEnumerable<T>インターフェイスし、その実装を使用して LINQ クエリを作成します。The following example demonstrates how to implement the IEnumerable<T> interface and uses that implementation to create a LINQ query. 実装する場合IEnumerable<T>、実装する必要がありますもIEnumerator<T>または、c# のみで使用することができます、 yieldキーワード。When you implement IEnumerable<T>, you must also implement IEnumerator<T> or, for C# only, you can use the yield keyword. 実装するIEnumerator<T>も必要ですIDisposableを実装するこの例では表示されます。Implementing IEnumerator<T> also requires IDisposable to be implemented, which you will see in this example.

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class App
{
    // Excercise the Iterator and show that it's more
    // performant.
    public static void Main()
    {
        TestStreamReaderEnumerable();
        Console.WriteLine("---");
        TestReadingFile();
    }

    public static void TestStreamReaderEnumerable()
	{
		// Check the memory before the iterator is used.
		long memoryBefore = GC.GetTotalMemory(true);
      IEnumerable<String> stringsFound;
		// Open a file with the StreamReaderEnumerable and check for a string.
      try {
         stringsFound =
               from line in new StreamReaderEnumerable(@"c:\temp\tempFile.txt")
               where line.Contains("string to search for")
               select line;
         Console.WriteLine("Found: " + stringsFound.Count());
      }
      catch (FileNotFoundException) {
         Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
         return;
      }

		// Check the memory after the iterator and output it to the console.
		long memoryAfter = GC.GetTotalMemory(false);
		Console.WriteLine("Memory Used With Iterator = \t"
            + string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
	}

    public static void TestReadingFile()
	{
		long memoryBefore = GC.GetTotalMemory(true);
      StreamReader sr;
      try {
         sr = File.OpenText("c:\\temp\\tempFile.txt");
      }
      catch (FileNotFoundException) {
         Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
         return;
      }

        // Add the file contents to a generic list of strings.
		List<string> fileContents = new List<string>();
		while (!sr.EndOfStream) {
			fileContents.Add(sr.ReadLine());
		}

		// Check for the string.
		var stringsFound = 
            from line in fileContents
            where line.Contains("string to search for")
            select line;

        sr.Close();
        Console.WriteLine("Found: " + stringsFound.Count());

		// Check the memory after when the iterator is not used, and output it to the console.
		long memoryAfter = GC.GetTotalMemory(false);
		Console.WriteLine("Memory Used Without Iterator = \t" + 
            string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
	}
}

// A custom class that implements IEnumerable(T). When you implement IEnumerable(T), 
// you must also implement IEnumerable and IEnumerator(T).
public class StreamReaderEnumerable : IEnumerable<string>
{
    private string _filePath;
    public StreamReaderEnumerable(string filePath)
    {
        _filePath = filePath;
    }

    // Must implement GetEnumerator, which returns a new StreamReaderEnumerator.
    public IEnumerator<string> GetEnumerator()
    {
        return new StreamReaderEnumerator(_filePath);
    }

    // Must also implement IEnumerable.GetEnumerator, but implement as a private method.
    private IEnumerator GetEnumerator1()
    {
        return this.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator1();
    }
}

// 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 : IEnumerator<string>
{
    private StreamReader _sr;
    public StreamReaderEnumerator(string filePath)
    {
        _sr = new StreamReader(filePath);
    }

    private string _current;
    // Implement the IEnumerator(T).Current publicly, but implement 
    // IEnumerator.Current, which is also required, privately.
    public string Current
    {

        get
        {
            if (_sr == null || _current == null)
            {
                throw new InvalidOperationException();
            }

            return _current;
        }
    }

    private object Current1
    {

        get { return this.Current; }
    }

    object IEnumerator.Current
    {
        get { return Current1; }
    }

    // Implement MoveNext and Reset, which are required by IEnumerator.
    public bool MoveNext()
    {
        _current = _sr.ReadLine();
        if (_current == null)
            return false;
        return true;
    }

    public void Reset()
    {
        _sr.DiscardBufferedData();
        _sr.BaseStream.Seek(0, SeekOrigin.Begin);
        _current = null;
    }

    // Implement IDisposable, which is also implemented by IEnumerator(T).
    private bool disposedValue = false;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposedValue)
        {
            if (disposing)
            {
                // Dispose of managed resources.
            }
            _current = null;
            if (_sr != null) {
               _sr.Close();
               _sr.Dispose();
            }
        }

        this.disposedValue = true;
    }

     ~StreamReaderEnumerator()
    {
        Dispose(false);
    }
}
// This example displays output similar to the following:
//       Found: 2
//       Memory Used With Iterator =     33kb
//       ---
//       Found: 2
//       Memory Used Without Iterator =  206kb
Imports System.IO
Imports System.Collections
Imports System.Collections.Generic
Imports System.Linq

Public Module App
   ' Excercise the Iterator and show that it's more performant.
   Public Sub Main()
      TestStreamReaderEnumerable()
      Console.WriteLine("---")
      TestReadingFile()
   End Sub

   Public Sub TestStreamReaderEnumerable()
		' Check the memory before the iterator is used.
		Dim memoryBefore As Long = GC.GetTotalMemory(true)
      Dim stringsFound As IEnumerable(Of String)
		' Open a file with the StreamReaderEnumerable and check for a string.
      Try
         stringsFound =
               from line in new StreamReaderEnumerable("c:\temp\tempFile.txt")
               where line.Contains("string to search for")
               select line
         Console.WriteLine("Found: {0}", stringsFound.Count())
      Catch e As FileNotFoundException
         Console.WriteLine("This example requires a file named C:\temp\tempFile.txt.")
         Return
      End Try

		' Check the memory after the iterator and output it to the console.
		Dim memoryAfter As Long = GC.GetTotalMemory(false)
		Console.WriteLine("Memory Used with Iterator = {1}{0} kb",
                        (memoryAfter - memoryBefore)\1000, vbTab)
   End Sub

   Public Sub TestReadingFile()
		Dim memoryBefore As Long = GC.GetTotalMemory(true)
      Dim sr As StreamReader
      Try
         sr = File.OpenText("c:\temp\tempFile.txt")
      Catch e As FileNotFoundException
         Console.WriteLine("This example requires a file named C:\temp\tempFile.txt.")
         Return
      End Try

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

		' Check for the string.
		Dim stringsFound =
            from line in fileContents
            where line.Contains("string to search for")
            select line

      sr.Close()
      Console.WriteLine("Found: {0}", stringsFound.Count())

		' Check the memory after when the iterator is not used, and output it to the console.
		Dim memoryAfter As Long = GC.GetTotalMemory(False)
		Console.WriteLine("Memory Used without Iterator = {1}{0} kb",
                        (memoryAfter - memoryBefore)\1000, vbTab)
   End Sub
End Module

' 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(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 StreamReader
    
    Public Sub New(filePath As String)
        _sr = New 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
                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 IEnumerator.MoveNext
        _current = _sr.ReadLine()
        if _current Is Nothing Then Return False

        Return True
    End Function

    Public Sub Reset() _
          Implements IEnumerator.Reset
        _sr.DiscardBufferedData()
        _sr.BaseStream.Seek(0, 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(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' Dispose of managed resources.
            End If

            _current = Nothing
            If _sr IsNot Nothing Then
               _sr.Close()
               _sr.Dispose()
            End If
        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 =     33kb
'       ---
'       Found: 2
'       Memory Used Without Iterator =  206kb

実装する方法を示す別の c# 例については、IEnumerable<T>インターフェイスを参照してください、ジェネリック サンプルします。For another C# example that demonstrates how to implement the IEnumerable<T> interface, see the Generics Sample. このサンプルでの使用、yieldキーワードの実装ではなくIEnumerator<T>します。This sample uses of the yield keyword instead of implementing IEnumerator<T>.

注釈

返されたIEnumerator<T>公開することで、コレクションを反復処理する機能を提供するCurrentプロパティ。コレクションでは、データを読み取ることが、コレクションを変更することがなく、列挙子を使用できます。The returned IEnumerator<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.

最初に、列挙子はコレクション内の 1 番目の要素の前に位置付けられます。Initially, the enumerator is positioned before the first element in the collection. この位置では、Current が未定義です。At this position, Current is undefined. そのため、呼び出す必要がある、MoveNextメソッドの値を読み取る前に、コレクションの最初の要素を列挙子を進めるCurrentします。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 まで同じオブジェクトを返しますMoveNextとしてもう一度呼び出されるMoveNext設定Current次の要素にします。Current returns the same object until MoveNext is called again as MoveNext sets Current to the next element.

場合MoveNext列挙子、コレクションの末尾がコレクション内の最後の要素の後に配置されているパスとMoveNext返しますfalseします。If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false. この位置では、後続の呼び出しで列挙子の場合MoveNextを返すこともfalseします。When the enumerator is at this position, subsequent calls to MoveNext also return false. 最後の呼び出し場合MoveNext返されるfalseCurrentが定義されていません。If the last call to MoveNext returned false, Current is undefined. Current を、再度、コレクションの最初の要素に設定することはできません。列挙子の新しいインスタンスを作成する必要があります。You cannot set Current to the first element of the collection again; you must create a new enumerator instance instead.

追加、変更、または、要素を削除するなど、コレクションに変更された場合、列挙子の動作は未定義です。If changes are made to the collection, such as adding, modifying, or deleting elements, the behavior of the enumerator is undefined.

列挙子には、コレクションへの排他アクセスはありませんので、コレクションが変更されない限り、列挙子は無効です。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. また、コレクションの列挙は、スレッド セーフなプロシージャではありません。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.

コレクションの既定の実装、System.Collections.Generic名前空間が同期されていません。Default implementations of collections in the System.Collections.Generic namespace aren't synchronized.

適用対象

こちらもご覧ください